До сих пор наши запросы обращались только к одной таблице за раз. Запросы могут обращаться к нескольким таблицам одновременно или обращаться к одной и той же таблице таким образом, что несколько строк таблицы обрабатываются одновременно. Запросы, которые обращаются к нескольким таблицам (или нескольким экземплярам одной и той же таблицы) одновременно, называются запросами на соединение . Они объединяют строки из одной таблицы со строками из второй таблицы с выражением, указывающим, какие строки должны быть объединены в пары. Например, чтобы вернуть все записи о погоде вместе с местоположением соответствующего города, базе данных необходимо сравнить cityстолбец каждой строки weatherтаблицы со nameстолбцом всех строк в citiesтаблице и выбрать пары строк, в которых эти значения совпадение. [4]Это можно сделать с помощью следующего запроса:
SELECT * FROM weather JOIN cities ON city = name;
city | temp_lo | temp_hi | prcp | date | name | location
---------------+---------+---------+------+------------+---------------+-----------
San Francisco | 46 | 50 | 0.25 | 1994-11-27 | San Francisco | (-194,53)
San Francisco | 43 | 57 | 0 | 1994-11-29 | San Francisco | (-194,53)
(2 rows)Обратите внимание на две особенности результирующего набора:
- Для города Хейворд нет строки результатов. Это связано с тем, что в таблице нет соответствующей записи
citiesдля Hayward, поэтому объединение игнорирует несопоставленные строки вweatherтаблице. Вскоре мы увидим, как это можно исправить. - Есть две колонки, содержащие название города. Это правильно, потому что списки столбцов из таблиц и объединены
weather.citiesОднако на практике это нежелательно, поэтому вы, вероятно, захотите указать выходные столбцы явно, а не использовать*:
SELECT city, temp_lo, temp_hi, prcp, date, location
FROM weather JOIN cities ON city = name;Поскольку у всех столбцов были разные имена, синтаксический анализатор автоматически нашел, к какой таблице они принадлежат. Если бы в двух таблицах были повторяющиеся имена столбцов, вам нужно было бы уточнить имена столбцов, чтобы показать, какой из них вы имели в виду, например:
SELECT weather.city, weather.temp_lo, weather.temp_hi,
weather.prcp, weather.date, cities.location
FROM weather JOIN cities ON weather.city = cities.name;
Считается хорошим стилем уточнять все имена столбцов в запросе на соединение, чтобы запрос не завершился ошибкой, если позже в одну из таблиц будет добавлено повторяющееся имя столбца.
Запросы соединения, которые мы видели до сих пор, также могут быть записаны в такой форме:
SELECT *
FROM weather, cities
WHERE city = name;
Этот синтаксис предшествует синтаксису JOIN/ ON, который был введен в SQL-92. Таблицы просто перечисляются в FROMпредложении, и в предложение добавляется выражение сравнения WHERE. Результаты этого старого неявного синтаксиса и нового явного синтаксиса JOIN/ ONидентичны. Но для читателя запроса явный синтаксис облегчает понимание его значения: условие соединения вводится собственным ключевым словом, тогда как ранее условие было смешано с WHEREпредложением вместе с другими условиями.
Теперь мы выясним, как мы можем вернуть записи Хейворда. Мы хотим, чтобы запрос сканировал weatherтаблицу и для каждой строки находил соответствующие citiesстроки. Если подходящая строка не найдена, мы хотим, чтобы некоторые « пустые значения » были заменены на citiesстолбцы таблицы. Такой запрос называется внешним соединением . (Соединения, которые мы видели до сих пор, являются внутренними соединениями .) Команда выглядит следующим образом:
SELECT *
FROM weather LEFT OUTER JOIN cities ON weather.city = cities.name;
city | temp_lo | temp_hi | prcp | date | name | location
---------------+---------+---------+------+------------+---------------+-----------
Hayward | 37 | 54 | | 1994-11-29 | |
San Francisco | 46 | 50 | 0.25 | 1994-11-27 | San Francisco | (-194,53)
San Francisco | 43 | 57 | 0 | 1994-11-29 | San Francisco | (-194,53)
(3 rows)Этот запрос называется левым внешним соединением , потому что таблица, упомянутая слева от оператора соединения, будет иметь каждую из своих строк в выходных данных по крайней мере один раз, тогда как таблица справа будет содержать только те строки, которые соответствуют какой-либо строке оператора соединения. левый стол. При выводе строки левой таблицы, для которой нет совпадения с правой таблицей, столбцы правой таблицы заменяются пустыми (нулевыми) значениями.
Упражнение: Существуют также правые внешние соединения и полные внешние соединения. Попробуйте узнать, что они делают.
Мы также можем присоединиться к таблице против самой себя. Это называется самосоединением . В качестве примера предположим, что мы хотим найти все записи о погоде, которые находятся в температурном диапазоне других записей о погоде. Поэтому нам нужно сравнить столбцы temp_loи temp_hiкаждой weatherстроки со столбцами temp_loи temp_hiвсех остальных weatherстрок. Мы можем сделать это с помощью следующего запроса:
SELECT w1.city, w1.temp_lo AS low, w1.temp_hi AS high,
w2.city, w2.temp_lo AS low, w2.temp_hi AS high
FROM weather w1 JOIN weather w2
ON w1.temp_lo < w2.temp_lo AND w1.temp_hi > w2.temp_hi;
city | low | high | city | low | high
---------------+-----+------+---------------+-----+------
San Francisco | 43 | 57 | San Francisco | 46 | 50
Hayward | 37 | 54 | San Francisco | 46 | 50
(2 rows)Здесь мы переименовали таблицу погоды как w1и w2, чтобы иметь возможность различать левую и правую стороны соединения. Вы также можете использовать эти виды псевдонимов в других запросах, чтобы сэкономить время на наборе текста, например:
SELECT *
FROM weather w JOIN cities c ON w.city = c.name;
Вы столкнетесь с этим стилем сокращения довольно часто.
[4] Это только концептуальная модель. Соединение обычно выполняется более эффективно, чем реальное сравнение каждой возможной пары строк, но это незаметно для пользователя.
0 комментариев