2.2.8 Чтение данных из нескольких таблиц с помощью операции соединенияВложенные запросы подходят для обработки нескольких таблиц до тех пор, пока результаты (столбцы в предложении SELECT) относятся к одной и той же таблице. Если же нам нужно извлечь данные из двух или более таблиц, при помощи вложенного запроса это сделать не удастся. Вместо этого необходимо использовать операцию соединения (join). Основная идея здесь — создать новое отношение, связав между собой содержимое двух или более исходных отношений. Рассмотрим следующий пример: SELECT Title, AskingPrice Смысл этого оператора заключается в том, что создается новая таблица с двумя столбцами Title и AskingPrice. Эти столбцы берутся соответственно из таблиц WORK и TRANSACTION при условии, что столбец WorkID в таблице WORK равен одноименному столбцу в таблице TRANSACTION. Обозначения WORK.WorkID и TRANSACTION.WorkID необходимы для устранения конфликта имен столбцов. Эту операцию можно представить себе следующим образом. Начнем с первой строки таблицы TRANSACTION. Возьмем значение столбца WorkID в данной строке (в табл. 1.3 это 505) и просмотрим строки таблицы WORK (табл. 1.2). Найдя в таблице WORK строку, где WorkID также равняется 505, соединим столбец Title только что найденной первой строки таблицы WORK со столбцом AskingPrice первой строки таблицы TRANSACTION. Первая строка таблицы WORK (см. табл. 1.2) имеет WorkID, равный 505, поэтому мы соединяем столбец Title первой строки таблицы WORK со столбцом AskingPrice первой строки таблицы TRANSACTION, и получаем тем самым первую строку соединения: Mystic Fabric 20000 Теперь, по-прежнему используя WorkiD=505. найдем следующую строку в отношении WORK, которая имеет WorkID, равный 505. Таких строк больше нет, поэтому переходим ко второй строке таблицы TRANSACTION. Так как в этой строке WorkID так же равен 505, снова найдем первую строку в отношении WORK, которая имеет WorkID, равный 505. Соединив столбец Title первой строки таблицы WORK со столбцом AskingPrice второй строки таблицы TRANSACTION, мы получим вторую строку соединения: Mystic Fabric 20000 Таким образом перебирая все строки отношения TRANSACTION получаем окончательный результат:
Таблицу, получившуюся в результате соединения, можно обрабатывать также, как и любую другую таблицу. Например, мы можем сгруппировать строки по названиям картин и просуммировать вырученные суммы по каждой из картин. Это сделает следующий запрос: SELECT Title, SUM(AskingPrice) Результатом будет следующая таблица: Slow Embers 15000 Предложение WHERE мы также можем применить в процессе создания соединения: SELECT Title, AskingPrice Результат соединения будет таким: Mystic Fabric 47000 Это такая же таблица, поэтому все описанные выше SQL-операторы к ней применимы. Теперь рассмотрим случай, когда требуется соединить три таблицы. Предположим, нам нужно знать по каждой картине вырученную сумму и имя художника. Для этого нам нужно соединить три таблицы: TRANSACTION (поле AskingPrice), WORK (поле Title) и ARTIST (поле Name): SELECT Title, AskingPrice, Name Результатом соединения будет следующая таблица:
В стандарте SQL-92 введен альтернативный синтаксис соединения, ставший весьма популярным, поскольку его легче интерпретировать. Здесь вместо WHERE используются ключевые слова JOIN и ON: SELECT Title, AskingPrice Результат имеет следующий вид:
Сделать оператор соединения более удобным для чтения можно, используя псевдонимы для имен таблиц. Выражение FROM WORK W присваивает таблице WORK псевдоним W. Это позволяет переписать предыдущий оператор следующим образом: SELECT Title, AskingPrice Соединение трех таблиц можно выполнить путем добавления предложения JOIN в конец первого оператора SELECT: SELECT W.Title, AskingPrice, A.Name FROM WORK W JOIN TRANSACTION T Следует обратить внимание, что когда требуется указать имя столбца в первой строке оператора SELECT, необходимо использовать псевдоним, а не имя таблицы. Так, в выше приведенном операторе SELECT используется запись W.Title, а не WORK.Title. По мере того, как запросы усложняются, этот формат оказывается легче интерпретировать, и именно он будет использоваться для соединений далее. На практике необходимо знать оба формата, поскольку и тот, и другой применяются в промышленности. Теперь рассмотрим различия между вложенным запросом и соединением. На практике соединение во многих случаях можно использовать в качестве альтернативы вложенным запросам. Например, ранее в разделе 2.2.7 был использован вложенный запрос для нахождения названия работ, которые были проданы галереей дороже 20000. Этот же запрос можно реализовать и с помощью соединения: SELECT DISTINCT Title Хотя ситуации, когда соединение можно использовать вместо вложенного запроса, нередки, такая замена все же возможна не всегда. Например, соединения не могут заменить коррелированные вложенные запросы, а также запросы с использованием ключевых слов EXISTS и NOT EXISTS (будут рассматриваться далее в других разделах пособия). И наоборот, не всегда вложенный запрос может служить заменой для соединения. В соединении запрашиваемые столбцы могут принадлежать любой из соединяемых таблиц, а во вложенном запросе все возвращаемые столбцы должны принадлежать только одной таблице, а именно той, которая указана в предложении FROM самого первого оператора SELECT. Например, в следующем вложенном запросе в результат войдут только столбцы таблицы ARTIST: SELECT DISTINCT Name Если нужно включить в результат столбцы WORK.Title, придется использовать соединение: SELECT A.Name, W.Title
|