- •Оглавление Извлечение данных. Оператор select
- •Оператор select
- •Предикаты (часть I)
- •Предикаты сравнения
- •Предикат between
- •Предикат in
- •Переименование столбцов и вычисления в результирующем наборе
- •Предикаты (часть 2) Предикат like
- •Использование значения null в условиях поиска Предикат is [not] null
- •Получение итоговых значений
- •Предложение group by
- •Предложение having
- •Использование в запросе нескольких источников записей
- •Явные операции соединения
- •Традиционные операции над множествами и оператор select
- •Декартово произведение
- •Объединение
- •Пересечение и разность
- •Предикат exists
- •Использование ключевых слов some | any и all с предикатами сравнения
- •Еще о подзапросах
- •Преобразование типов
- •Оператор case
- •Функции Transact-sql для обработки даты/времени
- •Функция dateadd
- •Функция datediff
- •Функция datepart
- •Функция datename
- •Функции работы со строками в ms sql server 2005
- •Функция substring
- •Функция reverse
- •Функция replace
- •Функции ltrim и rtrim
- •Функции lower и upper
- •Функция unicode
- •Функция nchar
- •Операторы модификации данных
- •Оператор insert
- •Вставка строк в таблицу, содержащую автоинкрементируемое поле
- •Оператор update
- •Оператор delete
- •Приложение 1. Описание учебных баз данных
- •1. Компьютерная фирма
- •2. Фирма вторсырья
- •3. Корабли
- •4. Аэрофлот
- •5. Окраска
- •Приложение 2. Список упражнений (select)
- •Как объединить данные из двух столбцов в один без использования union и join?
- •1. Union all
- •2. Full join
- •3. Unpivot
- •Комментарии
- •Как добавить новый столбец в таблицу между существующими столбцами?
- •Как вывести по n строк из каждой группы?
- •"Классическое" решение
- •1. Соединение
- •2. Подзапрос в предложении select
- •Решение на основе ранжирующих функций
- •Как удалить дубликаты строк из таблицы?
- •1. Нумерация строк
- •2. Ранжирование строк внутри групп дубликатов
- •3. Удаление дубликатов из виртуальной таблицы
- •Как удалить дубликаты строк при наличии первичного ключа?
- •Id name
- •Id_pk color
- •Id name color
- •Обновление таблицы t_details
- •Id_pk name color dup min_id
- •Id_pk color
- •Id name
- •Id_pk color
Явные операции соединения
В предложении FROM может быть указана явная операция соединения двух и более таблиц. Среди ряда операций соединения, описанных в стандарте языка SQL, многими серверами баз данных поддерживается лишь операция соединения по предикату. Синтаксис соединения по предикату имеет вид:
FROM <таблица 1> [INNER] | {{LEFT | RIGHT | FULL } [OUTER]} JOIN <таблица 2> [ON <предикат>]
Соединение может быть либо внутренним (INNER), либо одним из внешних (OUTER). Служебные слова INNER и OUTER можно опускать, поскольку внешнее соединение однозначно определяется его типом - LEFT (левое), RIGHT (правое) или FULL (полное), а просто JOIN будет означать внутреннее соединение.
Предикат определяет условие соединения строк из разных таблиц. При этом INNER JOIN означает, что в результирующий набор попадут только те соединения строк двух таблиц, для которых значение предиката равно TRUE. Как правило, предикат определяет эквисоединение по внешнему и первичному ключам соединяемых таблиц, хотя это не обязательно.
Пример. Найти производителя, номер модели и цену каждого компьютера, имеющегося в базе данных:
SELECT maker, Product.model AS model_1, PC.model AS model_2, price FROM Product INNER JOIN PC ON PC.model = Product.model ORDER BY maker, PC.model; |
В данном примере в результирующем наборе будут соединяться только те строки из таблиц PC и Product, у которых совпадают номера моделей. Для контроля в результат включен как номер модели из таблицы PC, так и из таблицы Product:
maker |
model_1 |
model_2 |
price |
A |
1232 |
1232 |
600.0 |
A |
1232 |
1232 |
400.0 |
A |
1232 |
1232 |
350.0 |
A |
1232 |
1232 |
350.0 |
A |
1233 |
1233 |
600.0 |
A |
1233 |
1233 |
950.0 |
A |
1233 |
1233 |
980.0 |
B |
1121 |
1121 |
850.0 |
B |
1121 |
1121 |
850.0 |
B |
1121 |
1121 |
850.0 |
E |
1260 |
1260 |
350.0 |
Внешнее соединение LEFT JOIN означает, что помимо строк, для которых выполняется условие предиката, в результирующий набор попадут все остальные строки из первой таблицы (левой). При этом отсутствующие значения полей из правой таблицы будут заполнены NULL-значениями.
Пример. Привести все модели ПК, их производителей и цену:
SELECT maker, Product.model AS model_1, PC.model AS model_2, price FROM Product LEFT JOIN PC ON PC.model = Product.model WHERE type = 'PC' ORDER BY maker, PC.model; |
Обратите внимание на то, что по сравнению с предыдущим примером, пришлось использовать предложение WHERE для отбора только производителей ПК. В противном случае в результирующий набор попали бы также и модели ПК-блокнотов и принтеров. В рассмотренном ранее примере это условие было бы излишним, т.к. соединялись только те строки, у которых совпадали номера моделей, и одной из таблиц была таблица PC, содержащая только ПК. В результате выполнения запроса получим:
maker |
model_1 |
model_2 |
price |
A |
1232 |
1232 |
600.0 |
A |
1232 |
1232 |
400.0 |
A |
1232 |
1232 |
350.0 |
A |
1232 |
1232 |
350.0 |
A |
1233 |
1233 |
600.0 |
A |
1233 |
1233 |
950.0 |
A |
1233 |
1233 |
980.0 |
B |
1121 |
1121 |
850.0 |
B |
1121 |
1121 |
850.0 |
B |
1121 |
1121 |
850.0 |
E |
2111 |
NULL |
NULL |
E |
2112 |
NULL |
NULL |
E |
1260 |
1260 |
350.0 |
Поскольку моделей 2111 и 2112 из таблицы Product нет в таблице PC, в полях из таблицы PC содержится NULL. Соединение RIGHT JOIN обратно соединению LEFT JOIN, т.е. в результирующий набор попадут все строки из второй таблицы, которые будут соединяться только с теми строками из первой таблицы, для которых выполняется условие соединения. В нашем случае левое соединение
Product LEFT JOIN PC ON PC.model = Product.model
будет эквивалентно правому соединению
PC RIGHT JOIN Product ON PC.model = Product.model
Запрос же
SELECT maker, Product.model AS model_1, PC.model AS model_2, price FROM Product RIGHT JOIN PC ON PC.model = Product.model ORDER BY maker, PC.model; |
даст те же результаты, что и внутреннее соединение, поскольку в правой таблице (PC) нет таких моделей, которые отсутствовали бы в левой таблице (Product), что вполне естественно для типа связи "один-ко-многим", которая имеется между таблицами PC и Product. Наконец, при полном соединении (FULL JOIN) в результирующую таблицу попадут не только те строки, которые имеют одинаковые значения в сопоставляемых столбцах, но и все остальные строки исходных таблиц, не имеющие соответствующих значений в другой таблице. В этих строках все столбцы той таблицы, в которой не было найдено соответствия, заполняются NULL-значениями. Полное соединение представляет собой комбинацию левого и правого внешних соединений. Так запрос для таблиц A и B, приведенных в начале главы,
SELECT A.*, B.* FROM A FULL JOIN B ON A.a = B.c; |
даст следующий результат:
a |
b |
c |
d |
1 |
2 |
NULL |
NULL |
2 |
1 |
2 |
4 |
NULL |
NULL |
3 |
3 |
Заметим, что это соединение симметрично, т.е. "A FULL JOIN B" эквивалентно "B FULL JOIN A". Обратите также внимание на обозначение A.*, что означает "все поля таблицы А".
Рекомендуемые упражнения: 6, 9, 13, 16, 19, 21, 34, 50, 55.