Объединение наборов данных
Внутренние и внешние объединения
На практике чаще используются внутренние и внешние объединения, при которых секция JOIN обязательно содержит критерий, уточняющий связи между объединяемыми наборами данных. Синтаксис внутренних и внешних объединений:
источник1 [ NATURAL ] тип_объединения источник2 [ ON (условие [….]) I USING (поле [,…]) ]
- источник1. Первый из объединяемых наборов данных (имя таблицы или подзапрос).
- [ NATURAL ]. Два набора данных объединяются по равным значениям одноименных полей (например, если обе таблицы содержат поле с именем id, то объединяются записи с совпадающими значениями полей id). При наличии ключевого слова NATURAL учитываются синонимы полей (если они были назначены), а секции ON и USING становятся не только ненужными, но и недопустимыми.
- тип_объединепия. В данном контексте допустимы следующие типы объединений: [INNER] JOIN (то есть JOIN без уточнения подразумевает INNER JOIN), LEFT [OUTER] JOIN, RIGHT [OUTER] JOIN и FULL [OUTER] JOIN.
- источник2. Второй из объединяемых наборов данных (имя таблицы или подзапрос).
- ON (условие […. ]). Отношение между источниками. В секции ON можно задать произвольный критерий по аналогии с тем, как задаются условия в секции WHERE. В критерии могут использоваться синонимы таблиц и полей.
- USING (поле [,… ]). Одноименные поля источников, по совпадающим значениям которых производится объединение. В отличие от NATURAL JOIN позволяет ограничиться некоторыми одноименными полями, тогда как NATURAL проводит объединение по всем одноименным полям. По аналогии с NATURAL в параметрах секции USING учитываются синонимы полей.
Внутренние объединения
Конструкция INNER JOIN была включена в стандарт SQL92 для того, чтобы условия объединения источников данных (условия JOIN) можно было отличить от условий принадлежности записей к итоговому набору (условия WHERE). Рассмотрим две команды SELECT, приведенные в листинге 4.36.
Листинг 4.36. Сравнение команд INNER JOIN и WHERE.
booktown=# SELECT title, last_name, first_name booktown-# FROM books, authors booktown-# WHERE (books.author_id = authors.id) booktown-# AND last_name = 'Geisel': title last_name | first_name The Cat in the Hat | Geisel | Theodor Seuss Bartholomew and the Oobleck | Geisel | Theodor Seuss (2 rows) booktown=# SELECT title, last_name, first_name booktown-# FROM books AS b INNER JOIN authors AS a booktown-# ON (b.author_id = a.id) Dooktown-# WHERE last_name = 'Geisel'; title | last_name | first_name The Cat in the Hat | Geisel | Theodor Seuss Bartholomew and the Oobleck | Geisel | Theodor Seuss (2 rows)
Две синтаксические формы в листинге 4.36 функционально идентичны и возвращают одинаковые результаты. Синтаксис INNER JOIN позволяет отделить критерий связи источников от критерия выбора записей, поскольку связи определяются только в секции ON. Это существенно упрощает чтение и модификацию запросов, поскольку программисту не приходится разбираться в смысле каждого условия в секции WHERE.
Обратите внимание: во втором запросе продемонстрировано назначение синонимов а и b в секции ON для таблиц books и authors соответственно. Подобное использование синонимов в секции ON абсолютно законно, более того – часто оно предпочтительно, поскольку программа становится более наглядной.