Основные запросы

В этом документе описывается классификация и синтаксическая структура основных операторов запросов, поддерживаемых YMatrix.


1 Табличные выражения

Табличное выражение обычно представляет собой предложение FROM, которое вычисляет таблицу. Хотя другие последующие за FROM предложения (например, списки) также считаются табличными выражениями, они не являются фокусом данного раздела и поэтому здесь не акцентируются. После предложения FROM может следовать одно или несколько предложений JOIN, ON, USING или подзапросы.

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

Примеры табличных выражений:

Синтаксис чтения данных из одной таблицы:

=# FROM <table_name>

1.1 Предложение FROM

1.1.1 Соединённые таблицы

Синтаксис соединения:

=# FROM t1 <join_type> t2 [join_condition]

Здесь <join_type> может быть INNER JOIN, LEFT JOIN, RIGHT JOIN или FULL JOIN. Первый тип — внутреннее соединение; последние три — внешние соединения.
INNER JOIN эквивалентно JOIN, что в свою очередь эквивалентно простой записи JOIN.

Предположим, есть две таблицы: t1 (с колонками c1, c2) и t2 (с колонками c1, c2):

=# FROM t1 INNER JOIN t2 ON t1.c1 = t2.c1 AND t1.c2 = t2.c2
=# FROM t1 LEFT JOIN t2 USING (c1,c2)

1.1.2 Подзапросы

Когда запрос содержит один или несколько вложенных запросов, он называется вложенным запросом. Внешний запрос известен как основной запрос, а внутренний — как подзапрос.

Подзапросы могут быть вложены на несколько уровней и могут появляться почти в любом месте запроса, включая SELECT, WHERE списки, табличные выражения и условия HAVING, FROM, ORDER BY. Данный раздел сосредоточен на подзапросах внутри табличных выражений.

Синтаксис:

=# FROM (SELECT * FROM <table_name>) AS <alias>

Предположим, есть таблица table1:

=# FROM (SELECT * FROM table1) AS t1

Это эквивалентно FROM table1.

1.2 Предложение WHERE

Предложение WHERE фильтрует строки на основе указанных условий. Синтаксис:

=# WHERE <condition>

Здесь <condition> может быть любым выражением значения, возвращающим числовой или логический результат.

Предположим, есть таблицы t1 (с колонкой c1), t2 (с колонкой c2) и t3 (с колонками c1, c2, c3):

=# SELECT ... FROM t1 WHERE c1 > 5;
=# SELECT ... FROM t1 WHERE c1 IN (1, 2, 3);
=# SELECT ... FROM t1 WHERE c1 IN (SELECT c1 FROM t2);
=# SELECT ... FROM t1 WHERE c1 IN (SELECT c3 FROM t2 WHERE c2 = t.c1 + 10);
=# SELECT ... FROM t1 WHERE c1 BETWEEN (SELECT c3 FROM t2 WHERE c2 = t.c1 + 10) AND 100;
=# SELECT ... FROM t1 WHERE EXISTS (SELECT c1 FROM t2 WHERE c2 > t.c1);

1.3 Предложения GROUP BY и HAVING

Эти предложения используются для группировки строк и выполнения агрегатных вычислений по каждой группе. Когда запрос содержит агрегатную функцию, используйте HAVING для фильтрации сгруппированных результатов вместо WHERE. Это связано с тем, что фильтры WHERE работают с исходными данными до группировки, тогда как фильтры HAVING применяются после агрегации.

1.3.1 Базовые агрегатные функции

YMatrix предоставляет следующие базовые агрегатные функции для вычислений по группам:

Функция Описание
count(/*) Количество ненулевых значений (count(*) включает null-значения)
sum() Сумма значений
avg() Среднее значение
min() Минимальное значение
max() Максимальное значение

Предположим, есть таблица t1 (с колонками c1, c2):

=#  SELECT count(*), 
           max(c1),
           c2 
    FROM t1
    GROUP BY c2;

Примечание!
Для расширенных агрегатных функций см. Расширенные запросы.

1.3.2 Предложение GROUP BY

Примечание!
Любая некагрегированная колонка в списке SELECT должна присутствовать в списке GROUP BY; в противном случае запрос завершится ошибкой.

Предположим, есть таблица t1 (с колонками c1, c2, c3):

-- Correct syntax
=# SELECT c1, avg(c2)
    FROM t1
    GROUP BY c1;

-- Correct syntax
=# SELECT c1, c2, avg(c3)
    FROM t1
    GROUP BY (c1,c2);

-- Incorrect syntax
=# SELECT c1, c2, avg(c3)
    FROM t1
    GROUP BY c1;

1.3.3 Предложение HAVING

Чтобы отфильтровать результаты агрегатных функций, используйте предложение HAVING вместо WHERE. Как уже упоминалось, WHERE применяется до группировки, а HAVING — после агрегации.

Предположим, есть таблица t1 (с колонками c1, c2):

-- Correct syntax
=# SELECT c1, max(c2)
    FROM t1
    GROUP BY c1
    HAVING avg(c2) < 60;

-- Incorrect syntax
=# SELECT c1, max(c2)
    FROM t1
    GROUP BY c1
    WHERE avg(c2) < 60;


2 Список SELECT

Список SELECT формирует временную виртуальную таблицу путём вычислений и определяет, какие колонки будут отображаться в конечном результате.

Например, выбрать колонки c1, c2, c3 из таблицы t1:

=# SELECT c1, c2, c3 FROM t1;

Выбрать колонки c1, c2 из t1 и колонку c1 из t2. Если в нескольких таблицах есть колонки с одинаковыми именами, их следует квалифицировать именем таблицы:

=# SELECT t1.c1, t2.c1, t1.c2 FROM t1,t2;

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

=# SELECT c1 AS value, c2 + 1 AS sum FROM t1,t2;

Ключевое слово AS является необязательным, но в данном примере, поскольку value также является зарезервированным ключевым словом в YMatrix, требуются двойные кавычки:

=# SELECT c1 "value", c2 + 1 AS sum FROM t1,t2;

Добавьте ключевое слово DISTINCT после SELECT, чтобы удалить дубликаты и обеспечить уникальность результата:

=# SELECT DISTINCT c1 FROM t1;


3 Комбинированные запросы

Комбинированные запросы используют ключевые слова UNION, INTERSECT или EXCEPT для объединения результирующих наборов двух запросов путём вычисления их объединения, пересечения или разности.

Синтаксис комбинирования двух запросов:

=# <query1> UNION [ALL] <query2>
=# <query1> INTERSECT [ALL] <query2>
=# <query1> EXCEPT [ALL] <query2>

Явное указание ALL сохраняет дублирующиеся строки в выводе.

Query 1 и Query 2 обозначают любые запросы, использующие описанные здесь возможности.

  • UNION добавляет результат Query 2 к Query 1 — то есть объединение обоих.
  • INTERSECT возвращает строки, присутствующие и в Query 1, и в Query 2 — то есть их пересечение.
  • EXCEPT возвращает строки из Query 1, которых нет в Query 2 — то есть разность множеств.

Пример с использованием UNION; аналогичный синтаксис применим и к другим операторам:

=# SELECT c1 FROM t1 UNION SELECT c2 FROM t2 LIMIT 10;

В этом запросе LIMIT 10 применяется к окончательному объединённому результату — то есть к (SELECT c1 FROM t1 UNION SELECT c2 FROM t2) LIMIT 10;.


4 Сортировка строк

Используйте предложение ORDER BY для сортировки результатов по указанным колонкам.

Определите псевдоним колонки с помощью AS и отсортируйте по нему (AS необязательно):

=# SELECT c1 + c2 AS sum FROM t1 ORDER BY sum;

Используйте ASC для сортировки по возрастанию (от меньшего к большему):

=# SELECT c1 FROM t1 ORDER BY c1 ASC;

Используйте DESC для сортировки по убыванию (от большего к меньшему):

=# SELECT c1 FROM t1 ORDER BY c1 DESC;

Параметры сортировки действуют независимо для каждой колонки. При сортировке по нескольким колонкам укажите направление сортировки для каждой отдельно. Оба следующих SQL-выражения сортируют c1 по возрастанию и c2 по убыванию:

=# SELECT c1, c2 FROM t1 ORDER BY c1 ASC, c2 DESC;
=# SELECT c1, c2 FROM t1 ORDER BY c1, c2 DESC;

По умолчанию, если направление не указано, используется сортировка по возрастанию.


5 LIMIT и OFFSET

Используйте LIMIT и OFFSET для ограничения количества возвращаемых строк. LIMIT ограничивает количество выводимых строк — например, LIMIT 1 возвращает только одну строку; LIMIT ALL не накладывает ограничений. OFFSET указывает, сколько строк пропустить перед возвратом результатов. После выполнения запроса система пропускает указанное количество строк и возвращает результаты, начиная со следующей строки.

Примечания по использованию:

  • Предложение OFFSET должно использоваться вместе с LIMIT. Если OFFSET опущено, LIMIT начинает работу с первой строки.
  • Пропуск OFFSET и использование только LIMIT допустимо и эквивалентно OFFSET 0.
  • OFFSET должно быть неотрицательным целым числом; в противном случае будет вызвана ошибка.
  • Строки, пропущенные с помощью OFFSET, всё равно вычисляются, поэтому большие смещения могут быть неэффективны.

Синтаксис:

=# SELECT <list>
    FROM <table_expression>
    [ ORDER BY ... ]
    [ LIMIT { <number> | ALL } ] [ OFFSET <number> ]

Предположим, есть таблица t1 (с колонкой c1). Чтобы просмотреть первые 10 строк в порядке убывания (10 наибольших значений):

=# SELECT c1 FROM t1
    ORDER BY c1 DESC
    LIMIT 10;

Чтобы просмотреть строки с 11 по 20:

=# SELECT c1 FROM t1
    ORDER BY c1 DESC
    LIMIT 10 OFFSET 10;

Этот запрос сначала сортирует данные, затем пропускает первые 10 строк (OFFSET 10) и ограничивает вывод следующими 10 строками — таким образом возвращаются строки с 11 по 20.


6 JOIN и USING

Используйте предложение JOIN с USING для выполнения соединений нескольких таблиц по указанным ключевым колонкам.

Предположим, есть таблица t1 (с колонками c1, c2) и таблица t2 (с колонкой c2):

=# SELECT t1.c1, t2.* FROM t2 JOIN t1 USING (c2) ORDER BY t2.c2 DESC LIMIT 10;