
Лекция 7. Язык sql. Выборка данных из нескольких таблиц.
Если требуются данные из более, чем одной таблицы базы данных, в предложении FROM команды SELECT указывается список этих таблиц через запятую. При этом, как правило, используется условие соединения, которое приводится в предложении WHERE.
Есть два основных типа условий соединения:
эквисоединения,
не-эквисоединения.
Кроме того, существуют дополнительные методы соединения:
внешние соединения,
соединения таблицы с собой.
В случае если условие соединения опущено или недействительно, результатом запроса будет декартово произведение всех таблиц указанных в предложении FROM, то есть будут получены все возможные комбинации строк этих таблиц.
Пример:
SELECT name, last_name
FROM s_dept, s_emp;
Результат:
NAME LAST_NAME
--------------- --------------
Finance Velasquez
Sales Velasquez
Sales Velasquez
Sales Velasquez
Sales Velasquez
Sales Velasquez
Operations Velasquez
Operations Velasquez
Operations Velasquez
Operations Velasquez
Operations Velasquez
Administration Velasquez
Finance Ngao
Sales Ngao
Sales Ngao
Sales Ngao
Sales Ngao
Sales Ngao
Operations Ngao
Operations Ngao
Operations Ngao
Operations Ngao
Operations Ngao
Administration Ngao
Finance Nagayama
Sales Nagayama
Sales Nagayama
Sales Nagayama
Sales Nagayama
Sales Nagayama
Operations Nagayama
…
300 rows selected.
В приведенном выше примере отсутствует предложение WHERE с условием соединения. Поэтому мы получили декартово произведение таблиц s_dept и s_emp: каждое значение столбца name таблицы s_dept соединилось с каждым значением столбца last_name таблицы s_dept. В таблице s_emp – 25 строк, в таблице s_dept – 12 строк, поэтому результатом запроса стала выборка из 25х12, то есть 300 строк. В случае, если мы добавим выборку столбца из еще одной таблицы, например, столбца address из таблицы s_customer, количество выбранных строк возрастет. Так как в таблице s_customer 15 строк, мы получим 25х12х15, то есть 4500 строк.
Как правило, декартово произведение содержит большое количество строк, при этом результат получается не очень полезным. Поэтому если вывод именно всех комбинаций строк не требуется, следует использовать условие соединения, которое задается в предложении WHERE.
Эквисоединения
Наиболее часто требуется произвести соединение по общим столбцам двух таблиц – по первичному и внешнему ключу. В этом случае в предложении WHERE задается условие равенства столбца из одной таблицы и соответствующего столбца из другой таблицы. При этом строки одной таблицы соединяются со строками другой согласно общим значениям в соответствующих столбцах.
Пример: Для каждого служащего вывести его фамилию и название отдела, в котором он работает.
Фамилии служащих находятся в таблице s_emp, в то время как названия отделов находятся в таблице s_dept. В таблице s_emp есть столбец dept_id, который содержит номер отдела служащего и является внешним ключом по отношению к таблице s_dept. В таблице s_dept также есть столбец, содержащий номер отдела – id, он является первичным ключом таблицы s_dept. Нам необходимо для каждого служащего из таблицы s_emp найти его номер отдела, а затем найти такой же номер отдела в таблице s_dept и по нему определить название отдела.
SELECT s_emp.last_name, s_dept.name
FROM s_dept, s_emp
WHERE s_emp.dept_id=s_dept.id;
Результат:
LAST_NAME NAME
------------- -------------
Velasquez Administration
Ngao Operations
Nagayama Sales
Quick-To-See Finance
Ropeburn Administration
Urguhart Operations
Menchu Operations
…
25 rows selected.
Обратите внимание, в приведенном выше примере имена столбцов предваряются именами таблиц, из которых должны быть выбраны эти столбцы. Дело в том, что в разных таблицах могут быть столбцы с одинаковыми именами. Например, в нашем примере и в таблице s_emp и в таблице s_dept есть столбец с именем id. Чтобы указать серверу, из какой именно таблицы выбирать столбцы, необходимо задавать префикс в виде имени таблицы перед каждым именем столбца, которое может быть истолковано неоднозначно. Имя таблицы и имя столбца при этом разделяются точкой. В случае, если префикс не будет указан, возникнет ошибка.
Пример: Для каждого служащего вывести его фамилию и название отдела, в котором он работает.
SELECT last_name, name
FROM s_dept, s_emp
WHERE dept_id=id;
Результат:
WHERE dept_id=id
*
ERROR at line 3:
ORA-00918: column ambiguously defined
Если одноименных столбцов в запросе нет, то указание имен таблиц вообще не обязательно. Но рекомендуется при выполнении выборки из нескольких таблиц в любом случае указывать имена таблиц, так как это увеличивает производительность обработки запроса сервером и улучшает читабельность запроса.
Если помимо условия соединения необходимо задать условия, ограничивающие выборку строк, эти условия записываются с помощью оператора AND.
Пример: Найти название отдела и название региона, в котором этот отдел находится для отдела №35 .
SELECT s_dept.name, s_region.name
FROM s_dept, s_region
WHERE s_dept.region_id=s_region.id
AND s_dept.id=35;
Результат:
NAME NAME
--------- -----------
Sales Europe
Предварение каждого имени столбца именем соответствующей таблицы может занять много времени, особенно, если запрос содержит большое количество имен столбцов, а имена таблиц длинные. Поэтому вместо имен можно использовать более короткие псевдонимы таблиц. Псевдоним таблицы задается после имени таблицы в предложении FROM и присваивает таблице другое имя в рамках одного конкретного запроса. Использование псевдонимов таблиц позволяет уменьшить объем кода SQL, что сокращает расход памяти.
Псевдонимы таблиц могут содержать до тридцати символов, но чем они короче, тем лучше. Если Вы задали псевдоним таблицы в предложении FROM, он должен использоваться вместо имени этой таблицы во всем тексте запроса.
Пример: Для каждой фирмы-клиента выбрать ее номер, наименование, фамилию ее торгового представителя и название региона, в котором она располагается.
SELECT c.id, c.name, e.last_name, r.name
FROM s_customer c, s_emp e, s_region r
WHERE c.sales_rep_id=e.id and c.region_id=r.id;
Результат:
ID NAME LAST_NAME NAME
-------- -------------------- ----------------- ------------------
201 Unisports Giljum South America
202 OJ Atheletics Nguyen Asia
203 Delhi Sports Nguyen Asia
204 Womansport Magee North America
205 Kam's Sporting Goods Dumas Asia
206 Sportique Dumas Europe
208 Muench Sports Dumas Europe
209 Beisbol Si! Magee North America
210 Futbol Sonora Giljum South America
…
14 rows selected.
Обратите внимание, в предыдущем примере соединяются три таблицы, поэтому задано 2 условия соединения. (Условие соединения таблицы s_customer и s_emp и условие соединения s_customer и s_region.) В любом случае при соединении n таблиц количество условий соединения должно быть как минимум n-1, в противном случае Вы получите декартово произведение таблиц.
Не-эквисоединения
Не-эквисоединения возникают, когда соединения производится не по общим столбцам. В этом случае обычно используются другие операторы сравнения, кроме равенства (>=, <=, <>, BETWEEN…AND… и т.п.).
Пример: Предположим, в базе данных имеется еще одна таблица: goods, содержащая список некоторых товаров. Таблица имеет следующие столбцы: name – наименование товара и cost – цена товара. Необходимо для каждого служащего определить список товаров, которые он может приобрести на свою месячную зарплату1.
-- Предположим, данные таблицы goods следующие:
SELECT *
FROM goods;
Результат:
NAME COST
----------- ---------
TV 2000
Kettle 500
Refrigerator 1500
-- Решением примера является запрос:
SELECT s_emp.last_name, s_emp.salary, goods.name, goods.cost
FROM s_emp, goods
WHERE s_emp.salary>=goods.cost;
Результат:
LAST_NAME SALARY NAME COST
-------------- --------- ------------ ---------
Velasquez 2500 TV 2000
Velasquez 2500 kettle 500
Velasquez 2500 refrigerator 1500
Ropeburn 1550 kettle 500
Ropeburn 1550 refrigerator 1500
Nguyen 1525 kettle 500
Nguyen 1525 refrigerator 1500
Sedeghi 1515 kettle 500
Sedeghi 1515 refrigerator 1500
Giljum 1490 kettle 500
Ngao 1450 kettle 500
…
30 rows selected.