Материал предоставлен http://it.rfet.ru

Выбор источников в секции FROM

В секции FROM указывается источник данных – таблица или итоговый набор. Секция может содержать несколько источников, разделенных запятыми. Результат подобного перечисления функционально эквивалентен перекрестному объединению, о котором рассказано в подразделе “Объединение наборов данных”.

Использование нескольких источников данных в PostgreSQL требует осторожности. В результате выполнения команды SELECT для нескольких источников без секций WHERE и JOIN, уточняющих связи между источниками, возвращается полное декартово произведение источников. Иначе говоря, итоговый набор содержит все возможные комбинации записей из всех источников.

Обычно для уточнения связей между источниками, перечисленными через запятую в секции FROM, используется секция WHERE. Пример приведен в листинге 15.

Листинг 15. Выборка из нескольких таблиц.

booktown=# SELECT books.id, title, authors_id, last_name FROM books, authors WHERE books.authored = authors.id;

id   | title               | id | last_name
190  | Little Women        | 16 | Alcott
156  | The Tell-Tale Heart | 115 | Рое
4142 | 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.

Точечная запись обязательна только при наличии неоднозначности между наборами данных. Как показано в листинге 15, ссылка может состоять только из имени поля – при условии, что это имя уникально во всех наборах данных, перечисленных в секции FROM. В приведенном примере поле title присутствует только в таблице books, а поле last_name входит только в таблицу authors, поэтому на их имена можно ссылаться без уточнения.

Если в качестве источника используется итоговый набор, созданный подзапросом, то весь подзапрос заключается в круглые скобки. По наличию круглых скобок PostgreSQL узнает о том, что команда SELECT интерпретируется как подзапрос, и выполняет ее перед выполнением внешней команды SELECT.

В листинге 16 приведен несколько необычный запрос, который производит выборку значений всех полей (*) таблицы books с использованием подзапроса. Затем из полученного набора “выбирается” строковая константа test и значение поля id.

Листинг 16. Выборка из подзапроса.

booktown=# SELECT 'test' AS test, id FROM (SELECT * FROM books) 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)

Странность запроса в листинге 16 заключается в том, что общий результат принципиально не отличается от прямой выборки из таблицы books, поскольку результат подзапроса идентичен ее содержимому. Строковая константа из одной команды SELECT комбинируется с данными из набора, полученного другой командой SELECT. Более реалистичный пример использования подзапросов приведен ниже в разделе “Подзапросы”, но сначала необходимо лучше разобраться в том, как работает команда SELECT.

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

Синонимы источников данных в секции FROM

Источникам данных в секции FROM – таблицам, подзапросам и т. д. – можно назначать синонимы в секции AS (по аналогии с отдельными полями). Синонимы часто используются для упрощения точечной записи, о которой говорилось в предыдущем разделе. Наличие синонима для набора данных позволяет обращаться к нему при помощи точечной записи, что делает команды SQL более компактными и наглядными. В листинге 16 приведен запрос из листинга 15 с упрощением точечной записи при помощи секции AS.

Листинг 16. Определение синонимов для источников данных.

SELECT b.id, title, a.id, last_name FROM books AS b, authors AS a WHERE b.author_id = a.id;

id  | title               | id |lastjname
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)

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

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

Примечание. Ключевое слово AS не является обязательным. Если оно отсутствует в команде, PostgreSQL считает, что все идентификаторы после ключевого слова FROM являются синонимами.

В листинге 17 приведен запрос из листинга 16, в котором полям id обеих таблиц назначаются уникальные идентификаторы, что позволяет ссылаться на них непосредственно (то есть без применения точечной записи). Синтаксис остается прежним, но на этот раз синоним назначается только полю id таблицы books, в результате ссылка на поле id таблицы authors становится однозначной.

Листинг 17. Определение синонимов для полей.

booktown=# SELECT the_book_id, title, id, last_name FROM books AS b (the_book_id), authors WHERE author_id = 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Удаление дубликатов и ключевое слово DISTINCT