Обзор SELECT
Определение
Возвращает результат вычисления выражений, указанных после SELECT. Может использоваться в сочетании с другими операциями для получения иного эффекта.
Примеры:
SELECT "Hello, world!";
SELECT 2 + 2;
Процедура выполнения SELECT
Результат запроса SELECT вычисляется следующим образом:
- определяется набор входных таблиц – вычисляются выражения после FROM;
- к входным таблицам применяется SAMPLE / TABLESAMPLE;
- выполняется FLATTEN COLUMNS или FLATTEN BY; алиасы, заданные во
FLATTEN BY, становятся видны после этой точки; - выполняются все JOIN;
- к полученным данным добавляются (или заменяются) колонки, заданные в GROUP BY ... AS ... (выполняется после
WHEREначиная с версии 2025.02); - выполняется WHERE - все данные не удовлетворяющие предикату отфильтровываются;
- выполняется GROUP BY, вычисляются значения агрегатных функций;
- выполняется фильтрация HAVING;
- вычисляются значения оконных функций;
- вычисляются выражения в
SELECT; - выражениям в
SELECTназначаются имена заданные алиасами; - к полученным таким образом колонкам применяется top-level DISTINCT;
- таким же образом вычисляются все подзапросы в операторах UNION [ALL], INTERSECT [ALL], EXCEPT [ALL] и выполняется их объединение, пересечение, исключение соответственно; в текущей реализации комбинация
INTERSECT [ALL],EXCEPT [ALL]иUNION [ALL]не поддерживается, также не поддерживается использование более одного оператораINTERSECT [ALL]илиEXCEPT [ALL]вSELECTвыражении; - выполняется сортировка согласно ORDER BY;
- к полученному результату применяются OFFSET и LIMIT.
Порядок колонок в YQL
В стандартном SQL порядок колонок указанных в проекции (в SELECT) имеет значение. Помимо того, что порядок колонок должен сохраняться при отображении результатов запроса или при записи в новую таблицу, некоторые конструкции SQL этот порядок используют.
Это относится в том числе к операторам UNION [ALL], INTERSECT [ALL], EXCEPT [ALL] и к позиционному ORDER BY (ORDER BY ordinal).
По умолчанию в YQL порядок колонок игнорируется:
- порядок колонок в выходных таблицах и в результатах запроса не определен
- схема данных результата
UNION [ALL],INTERSECT [ALL]иEXCEPT [ALL]выводится по именам колонок, а не по позициям
При включении PRAGMA OrderedColumns; порядок колонок сохраняется в результатах запроса и выводится из порядка колонок во входных таблицах по следующим правилам:
SELECTс явным перечислением колонок задает соответствующий порядок;SELECTсо звездочкой (SELECT * FROM ...) наследует порядок из своего входа;- порядок колонок после JOIN: сначала колонки левой стороны, потом правой. Если порядок какой-либо из сторон присутствующей в выходе
JOINне определен, порядок колонок результата также не определен; - порядок
UNION [ALL],INTERSECT [ALL]иEXCEPT [ALL]зависит от режима выполнения; - порядок колонок для AS_TABLE не определен;
Комбинация запросов
Результаты нескольких SELECT (или подзапросов) могут быть объединены с помощью ключевых слов UNION и UNION ALL.
query1 UNION [ALL] query2 (UNION [ALL] query3 ...)
Объединение более двух запросов интерпретируется как левоассоциативная операция, то есть
query1 UNION query2 UNION ALL query3
интерпретируется как
(query1 UNION query2) UNION ALL query3
Пересечение только двух SELECT (или подзапросов) может быть вычислено с помощью ключевых слов INTERSECT и INTERSECT ALL.
query1 INTERSECT query2
Запрос из нескольких операторов INTERSECT [ALL] не допускается.
query1 INTERSECT query2 INTERSECT query3 ... -- ошибка
query1 INTERSECT query2 INTERSECT ALL query3 ... -- ошибка
Исключение только двух SELECT (или подзапросов) может быть вычислено с помощью ключевых слов EXCEPT и EXCEPT ALL.
query1 EXCEPT query2
Запрос из нескольких операторов EXCEPT [ALL] не допускается.
query1 EXCEPT query2 EXCEPT query3 -- ошибка
query1 EXCEPT query2 EXCEPT ALL query3 -- ошибка
Одновременное использование двух разных операторов UNION, INTERSECT и EXCEPT в одном запросе не допускается.
query1 UNION query2 INTERSECT query3 -- ошибка
query1 UNION query2 EXCEPT query3 -- ошибка
query1 INTERSECT query2 EXCEPT query3 -- ошибка
Данное поведение не зависит от наличия или отсутствия DISTINCT / ALL.
query1 UNION ALL query2 INTERSECT ALL query3 -- ошибка
query1 UNION ALL query2 EXCEPT ALL query3 -- ошибка
query1 INTERSECT ALL query2 EXCEPT ALL query3 -- ошибка
Важно
Только UNION и UNION ALL могут использоваться несколько раз (больше 1). Использование INTERSECT, INTERSECT ALL, EXCEPT и EXCEPT ALL несколько раз не допускается.
При наличии ORDER BY/LIMIT/DISCARD/INTO RESULT в объединяемых подзапросах применяются следующие правила:
ORDER BY/LIMIT/INTO RESULTдопускается только после последнего подзапроса;DISCARDдопускается только перед первым подзапросом;- указанные операторы действуют на результат
UNION [ALL],INTERSECT [ALL]илиEXCEPT [ALL], а не на подзапрос; - чтобы применить оператор к подзапросу, подзапрос необходимо взять в скобки.
Обращение к нескольким таблицам в одном запросе
В стандартном SQL для выполнения запроса по нескольким таблицам используется UNION ALL, который объединяет результаты двух и более SELECT. Это не совсем удобно для сценария использования, в котором требуется выполнить один и тот же запрос по нескольким таблицам (например, содержащим данные на разные даты). В YQL, чтобы было удобнее, в SELECT после FROM можно указывать не только одну таблицу или подзапрос, но и вызывать встроенные функции, позволяющие объединять данные нескольких таблиц.
Для этих целей определены следующие функции:
CONCAT(`table1`, `table2`, `table3` VIEW view_name, ...) — объединяет все перечисленные в аргументах таблицы.
EACH($list_of_strings) или EACH($list_of_strings VIEW view_name) — объединяет все таблицы, имена которых перечислены в списке строк. Опционально можно передать несколько списков в отдельных аргументах по аналогии с CONCAT.
Важно
Порядок, в котором будут объединены таблицы, всеми вышеперечисленными функциями не гарантируется.
Список таблиц вычисляется до запуска самого запроса. Поэтому созданные в процессе запроса таблицы не попадут в результаты функции.
По умолчанию схемы всех участвующих таблиц объединяются по правилам UNION ALL. Если объединение схем не желательно, то можно использовать функции с суффиксом _STRICT, например CONCAT_STRICT, которые работают полностью аналогично оригинальным, но считают любое расхождение в схемах таблиц ошибкой.
Все аргументы описанных выше функций могут быть объявлены отдельно через именованные выражения. В этом случае в них также допустимы и простые выражения посредством неявного вызова EvaluateExpr.
Имя исходной таблицы, из которой изначально была получена каждая строка, можно получить при помощи функции TablePath().
Примеры
USE some_cluster;
SELECT * FROM CONCAT(
`table1`,
`table2`,
`table3`);
USE some_cluster;
$indices = ListFromRange(1, 4);
$tables = ListMap($indices, ($index) -> {
RETURN "table" || CAST($index AS String);
});
SELECT * FROM EACH($tables); -- идентично предыдущему примеру