Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
SQL.doc
Скачиваний:
19
Добавлен:
14.03.2016
Размер:
382.46 Кб
Скачать

Декартово произведение

Ранее мы уже рассмотрели реализацию декартова произведения, состоящую в перечислении через запятую табличных выражений в предложении FROM (таблицы, представления, подзапросы) при отсутствии предложения WHERE, связывающего столбцы из перечисленных источников строк. Кроме того, можно использовать еще и явную операцию соединения – CROSS JOIN, например:

  1. SELECT Laptop.model, Product.model

  2. FROM Laptop CROSS JOIN

  3. Product;

Напомним, что при декартовом произведении каждая строка из первой таблицы соединяется с каждой строкой второй таблицы. В результате количество строк результирующего набора равно произведению количества строк операндов декартова произведения. В нашем примере таблица Laptop содержит 5 строк, а таблица Product — 16. В результате получается 5 * 16 = 80 строк

Примечание:

В чистом виде декартово произведение практически не используется, оно, как правило, является промежуточным результатом выполнения операции горизонтальной проекции (выборки) при наличии в операторе SELECT предложения WHERE.

Коррелирующие подзапросы

Коррелирующие подзапросы позволяют иногда очень кратко написать запросы, которые могут выглядеть весьма громоздко при использовании других языковых средств. Напомним, что коррелирующий подзапрос — это подзапрос, который содержит ссылку на столбцы из включающего его запроса (назовем его основным). Таким образом, коррелирующий подзапрос будет выполняться для каждой строки основного запроса, так как значения столбцов основного запроса будут меняться.

Пример: Требуется определить дату и рейсы каждого пассажира, совершенные им в свой последний полетный день.

Иными словами, нужно определить максимальную дату полета для каждого пассажира и найти все его рейсы за эту дату. С определением максимальной даты нет никаких проблем:

  1. SELECT id_psg, MAX(date)

  2. FROM pass_in_trip

  3. GROUP BY id_psg;

Однако тут нет рейса. Если мы попытаемся включить рейс в список вывода:

  1. SELECT id_psg, trip_no, MAX(date)

  2. FROM pass_in_trip

  3. GROUP BY id_psg;

то получим сообщение об ошибке, так как номер рейса не используется в агрегатной функции и не входит список столбцов группировки. Если включить номер рейса в этот список:

  1. SELECT id_psg, trip_no, MAX(date)

  2. FROM pass_in_trip

  3. GROUP BY id_psg, trip_no;

мы получим последний полет пассажира каждым рейсом, которым он летал. Это совсем не та задача, которую мы пытаемся решить. Применение коррелирующего подзапроса

  1. SELECT id_psg, trip_no, [date]

  2. FROM pass_in_trip pt_1

  3. WHERE [date] = (SELECT MAX([date])

  4. FROM pass_in_trip pt_2

  5. WHERE pt_1.id_psg = pt_2.id_psg );

Дает то, что нужно.

Здесь для каждого рейса проверяется, совершен ли он в последний полетный день данного пассажира. При этом если таких рейсов было несколько, мы получим их все.

Очевидным недостатком приведенного решения как раз и является то, что подзапрос должен вычисляться для каждой строки основного запроса. Чтобы избежать этого, можно предложить альтернативное решение, использующее соединение таблицы Pass_in_trip с приведенным в самом начале подзапросом, который вычисляет максимальные даты по каждому пассажиру:

  1. SELECT pt_1.id_psg, trip_no, [date]

  2. FROM pass_in_trip pt_1 JOIN

  3. (SELECT id_psg, MAX([date]) md

  4. FROM pass_in_trip

  5. GROUP BY id_psg

  6. ) pt_2 ON pt_1.id_psg = pt_2.id_psg AND

  7. [date] = md

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]