Опубликован: 28.12.2011 | Доступ: свободный | Студентов: 7561 / 1027 | Оценка: 3.81 / 3.53 | Длительность: 19:30:00
ISBN: 978-5-9963-0488-2
Лекция 8:

Соединения таблиц в предложении SELECT

Аннотация: Рассматриваются основы построения соединений таблиц в запросах SELECT и возможности построения соединений в Oracle.

Операция соединения в предложении SELECT

Запрос SELECT считается соединением, если обращается к нескольким источникам данных при том, что столбцы разных источников сравниваются друг с другом (в общем случае условным выражением общего вида). Соединение является одной из основных операций в реляционной модели, а в SQL она попала в искаженном виде по причине необязательности в SQL правила ключа применительно к таблицам.

Операция соединения издавна привлекала внимание разработчиков СУБД, так как, во-первых, ее присутствие в прикладной системе неизбежно обусловлено применением к БД теоретически обоснованной нормализации отношений/таблиц, а во-вторых, непродуманно прямолинейная отработка соединения чревата большими затратами СУБД.

По этим причинам операция соединения в свое время подробно исследовалась, подверглась систематизации и получила собственное синтаксическое оформление.

Виды соединений

Пример записи соединения таблиц в SQL:

SELECT emp.deptno, dname 
FROM   emp, dept
WHERE  emp.deptno = dept.deptno
;

Возможные варианты соотношений между данными в соединяемых столбцах:

  • столбцы заполнены одинаково;
  • данные одного столбца составляют подмножество данных другого;
  • данные двух столбцов пересекаются между собой;
  • данные столбцов не пересекаются.

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

Тетасоединение

Примерный вид:

SELECT * 
FROM   emp, dept
WHERE  emp.deptno <оператор_сравнения> dept.deptno

(когда оператор сравнения произвольный).

Эквисоединение

Примерный вид:

SELECT * 
FROM   emp, dept
WHERE  emp.deptno = dept.deptno
;

(экви соединение, когда оператор сравнения — равенство).

Естественное соединение

Примерный вид:

SELECT emp.*, dept.dname, dept.loc 
FROM   emp, dept
WHERE  emp.deptno = dept.deptno
;

(когда оператор сравнения — равенство и соединяемые столбцы в таблицах именованы одинаково).

Полнота соединений

Имеются следующие виды соединений, диктующие разные схемы отбора строк в результат:

  • закрытое;
  • полуоткрытое "левое";
  • полуоткрытое "правое";
  • открытое полное;
  • антисоединения, "правое" и "левое";

На приводимом рисунке фигурными скобками обозначены строки, отбираемые для построения результата соединений перечисленных видов:

Приводившийся выше пример естественного соединения является одновременно примером закрытого соединения, так как сравнение значений столбцов выполняется для всех строк с присутствующими значениями в паре (в более общем случае — в тройке, четверке и т. д.) столбцов.

Обратите внимание, что полуоткрытые соединения порождают строки с NULL, при том что эти NULL имеют смысл "значение неприменимо". Это способно породить ту же проблему выбора способа дальнейшей обработки результата, что возникала в запросах с GROUP BY ROLLUP и CUBE. Однако здесь специальной функции-различителя нет, и смысл пропущенного значения должен определяться программистом на основе его местонахождения.

Ярослав Прозоров
Ярослав Прозоров

В лекции № 7 "Введение в Oracle SQL" в подразделе "Несамостоятельность группировки с обобщениями ROLLUP, CUBE и GROUPING SETS"  представленная таблица сравнения содержит ошибки - окончания запросов пропущены. Видимо, ошибки вызваны некорректным переносом материала лекции.

Володимир Миколайчук
Володимир Миколайчук
Помогите разобраться поетапно с логикой запроса
-------TOOLS
NAME PRICE TYPE
drill 155 A
sawzall 192 N
mitre saw 292 M
router 86 I
RAD 145 M
jigsaw 128 I
screwdriver 77 P
------TOOL_TYPES
TYPE USAGE
A Always
I Often
M Sometimes
N Rarely
P Never

Запрос SQL:
SELECT t.type, SUM(t.price)
FROM tools t
GROUP BY t.type
HAVING SUM(t.price) >= (SELECT AVG(price)
FROM tools
WHERE type IN (SELECT type
FROM tool_types
WHERE usage = 'Often'));

И сколько строк он все таки вернет