Выбор источников в секции FROM
В секции FROM указывается источник данных – таблица или итоговый набор. Секция может содержать несколько источников, разделенных запятыми. Результат подобного перечисления функционально эквивалентен перекрестному объединению, о котором рассказано в подразделе "Объединение наборов данных".
Использование нескольких источников данных в PostgreSQL требует осторожности. В результате выполнения команды SELECT для нескольких источников без секций WHERE и JOIN, уточняющих связи между источниками, возвращается полное декартово произведение источников. Иначе говоря, итоговый набор содержит все возможные комбинации записей из всех источников.
Обычно для уточнения связей между источниками, перечисленными через запятую в секции FROM, используется секция WHERE. Пример приведен в листинге 4.27 (за дополнительной информацией о секции WHERE обращайтесь к подразделу "Уточнение запросов").
Листинг 4.27. Выборка из нескольких таблиц.
booktown=# SELECT books.id, title, authors_id, last_name booktown-# FROM books, authors booktown-# WHERE books.authored = authors.id; id | title | id | last_name 190 | Little Women | 16 | Alcott 156 | The Tell-Tale Heart | 115 | Рое 41472 | Practical PostgreSQL | 1212 | Worsley 2038 | Dynamic Anatomy | 1644 | Hogarth 1608 | The Cat in the Hat | 1809 | Geisel 1590 |Bartholomew and the Oobleck | 1809 | Geisel 4513 | Dune | 1866 | Herbert 4267 | 2001: A Space Odyssey | 2001 | Clarke 1501 | Goodnight Moon | 2031 | Brown 7808 | The Shining | 4156 | King 41473 |Programming Python | 7805 | Lutz 41477 |Learning Python | 7805 | Lutz 41478 | Perl Cookbook | 7806 | Christiansen 25908 | Franklin in the Dark | 15990 | Bourgeois 1234 | The Velveteen Rabbit | 25041 | Bianco (15 rows)
При использовании ссылок на имена полей, относящихся к разным источникам, может возникнуть неоднозначность. Предположим, команда SELECT получает исходные данные из таблиц books и authors. В каждой из этих таблиц имеется поле с именем id. Без дополнительных уточнений PostgreSQL не сможет определить, к какой таблице относится ссылка на поле id в следующей команде:
booktown=# SELECT id FROM books, authors ERROR: Column reference "id" is ambiguous
Для предотвращения неоднозначности в "полные" имена столбцов включается имя таблицы. При этом используется специальный синтаксис, называемый точечной записью (название связано с тем, что имя таблицы отделяется от имени поля точкой). Например, books.id означает поле id таблицы books.
Точечная запись обязательна только при наличии неоднозначности между наборами данных. Как показано в листинге 4.27, ссылка может состоять только из имени поля – при условии, что это имя уникально во всех наборах данных, перечисленных в секции FROM. В приведенном примере поле title присутствует только в таблице books, а поле last_name входит только в таблицу authors, поэтому на их имена можно ссылаться без уточнения.
Если в качестве источника используется итоговый набор, созданный подзапросом, то весь подзапрос заключается в круглые скобки. По наличию круглых скобок PostgreSQL узнает о том, что команда SELECT интерпретируется как подзапрос, и выполняет ее перед выполнением внешней команды SELECT.
В листинге 4.28 приведен несколько необычный запрос, который производит выборку значений всех полей (*) таблицы books с использованием подзапроса. Затем из полученного набора "выбирается" строковая константа test и значение поля id.
Листинг 4.28. Выборка из подзапроса.
booktown=# SELECT 'test' AS test, id booktown-# FROM (SELECT * FROM books) booktown-# AS example_sub_query; test | id test | 7808 test | 4513 test | 4267 test | 1608 test | 1590 test | 25908 test | 1501 test | 190 test | 1234 test | 2038 test | 156 test | 41472 test | 41473 test | 41477 test | 41478 (15 rows)
Странность запроса в листинге 4.28 заключается в том, что общий результат принципиально не отличается от прямой выборки из таблицы books, поскольку результат подзапроса идентичен ее содержимому. Строковая константа из одной команды SELECT комбинируется с данными из набора, полученного другой командой SELECT. Более реалистичный пример использования подзапросов приведен ниже в разделе "Подзапросы", но сначала необходимо лучше разобраться в том, как работает команда SELECT.
Примечание
Необязательное ключевое слово ONLY перед именем таблицы, которая является базовой по отношению к другим таблицам, означает, что выборка из производных таблиц не выполняется (наследование рассматривается в главе 7).