SELECT
Содержание раздела
Запрос позволяет выбрать данные из логических таблиц, логических представлений и (или) материализованных представлений или получить информацию о запросе к данным. Возможен запрос к срезу данных на указанный момент времени.
Запрос обрабатывается в порядке, описанном в разделе Порядок обработки запросов на чтение данных. В ответе возвращается:
- объект ResultSet c выбранными записями или информацией о запросе при успешном выполнении запроса;
- исключение при неуспешном выполнении запроса.
Запрос также можно использовать как подзапрос в следующих запросах:
- на выгрузку данных,
- на создание или обновление логического представления,
- на создание материализованного представления.
Синтаксис
SELECT column_list
FROM [db_name.]entity_name
[FOR SYSTEM_TIME time_expression [AS alias_name]]
[DATASOURCE_TYPE = datasource_alias]
[ESTIMATE_ONLY]
Где:
column_list
— список выбираемых столбцов таблицы или представления. Можно указывать символ*
для выбора всех столбцов;db_name
— имя логической базы данных, из которой выбираются данные. Указывается опционально, если выбрана логическая БД, используемая по умолчанию;entity_name
— имя таблицы или представления, из которого выбираются данные;time_expression
— выражение, задающее момент или период времени, за который выбираются данные или изменения данных. Синтаксис выражения см. ниже;alias_name
— псевдоним таблицы или представления. Может включать латинские буквы, цифры и символы подчеркивания;datasource_alias
— системный псевдоним СУБД хранилища, из которой выбираются данные. Возможные значения:'adb'
,'adqm'
,'adg'
,'adp'
.
В запросах можно указывать:
- ключевые слова, перечисленные в секции Поддерживаемые ключевые слова,
- функции, перечисленные в разделе Поддержка SQL,
- псевдонимы для имен таблиц, представлений и столбцов.
Примечание: некоторые агрегатные функции и типы соединений недоступны для исполнения в определенных СУБД хранилища. Список доступных возможностей см. в разделе Поддержка SQL.
Поддерживаемые ключевые слова
В запросе можно использовать следующие ключевые слова, которые должны быть указаны в порядке их перечисления:
FOR SYSTEM_TIME
— для указания момента времени или периода, за который выбираются данные или изменения данных. Если ключевое слово не указано, из логической таблицы и логического представления выбираются данные, актуальные на момент обработки запроса, из материализованного представления — данные, актуальные на момент последней синхронизации представления. Описание синтаксиса см. в секции Ключевое слово FOR SYSTEM_TIME;JOIN ON
— для соединения данных нескольких логических таблиц и (или) представлений из одной или нескольких логических БД. Возможные префиксы см. в секции Возможные типы соединений (префиксы JOIN);WHERE
— для указания условий выбора данных;GROUP BY
— для группировки данных;HAVING
— для указания условий выбора сгруппированных данных;ORDER BY
— для сортировки данных;LIMIT
илиFETCH NEXT <N> ROWS ONLY
— для ограничения количества возвращаемых строк;OFFSET
— для пропуска указанного количества строк в результате запроса. Описание синтаксиса см. в секции Ключевое слово OFFSET;DATASOURCE_TYPE
— для указания СУБД хранилища, из которой выбираются данные;ESTIMATE_ONLY
— для получения информации о запросе, а не самих данных. Описание см. в секции Ключевое слово ESTIMATE_ONLY.
Ключевое слово FOR SYSTEM_TIME
Ключевое слово FOR SYSTEM_TIME
позволяет указать момент, по состоянию на который запрашиваются данные, или период (диапазон дельт), за который запрашиваются изменения. Ключевое слово относится к логической таблице, логическому представлению или материализованному представлению, после имени которого оно следует. Если в запросе соединяется несколько логических таблиц и представлений, для каждой логической сущности можно указать свое ключевое слово FOR SYSTEM_TIME
, при этом значения этих ключевых слов могут различаться (см. пример ниже).
Примечание: наличие и значение ключевого слова FOR SYSTEM_TIME
для материализованного представления влияют на порядок маршрутизации запроса (см. раздел Маршрутизация запросов к данным материализованных представлений).
Ключевое слово указывается в формате FOR SYSTEM_TIME time_expression
, где выражение time_expression
принимает одно из следующих значений:
AS OF 'YYYY-MM-DD hh:mm:ss'
— запрос данных, актуальных на указанную дату и время. Возможные форматы даты и времени см. в разделе Форматы даты и времени в запросах;AS OF DELTA_NUM delta_num
— запрос данных, актуальных на дату и время закрытия дельты с номеромdelta_num
;AS OF LATEST_UNCOMMITTED_DELTA
— запрос данных на текущий момент, включая данные, загруженные в рамках открытой (горячей) дельты. По горячей дельте возвращаются записи, загруженные в рамках непрерывного диапазона завершенных операций записи (см. параметрыcn_from
иcn_to
в разделе GET_DELTA_HOT);STARTED IN (delta_num1, delta_num2)
— запрос данных, добавленных или измененных в период между дельтойdelta_num1
и дельтойdelta_num2
(включительно);FINISHED IN (delta_num1, delta_num2)
— запрос данных, удаленных в период между дельтойdelta_num1
и дельтойdelta_num2
(включительно).
Следующие значения ключевого слова не поддерживаются в запросах к материализованным представлениям:
FOR SYSTEM_TIME AS OF LATEST_UNCOMMITTED_DELTA
;FOR SYSTEM_TIME AS OF STARTED IN (delta_num1, delta_num2)
, если хотя бы одна дельта из диапазона отсутствует в материализованном представлении;FOR SYSTEM_TIME AS OF FINISHED IN (delta_num1, delta_num2)
, если хотя бы одна дельта из диапазона отсутствует в материализованном представлении.
Поддерживаемые типы соединений (префиксы JOIN)
Поддерживаются следующие типы соединений:
[INNER]
— внутреннее соединение,NATURAL
— внутреннее соединение по всем столбцам с одинаковыми именами, ключи соединения не указываются,LEFT [OUTER]
— левое внешнее соединение,RIGHT [OUTER]
— правое внешнее соединение,FULL [OUTER]
— полное внешнее соединение,CROSS
— декартово произведение таблиц или представлений, ключи соединения не указываются.
Ключевое слово OFFSET
Ключевое слово OFFSET
позволяет пропустить первые несколько строк результата и выбрать только последующие строки. В качестве значения ключевого слова можно указать любое неотрицательное целое число, начиная с нуля, или переменную. Если для OFFSET
указано значение 0, то пропускается 0 строк, что равносильно запросу без OFFSET
.
Запросы с OFFSET
без ограничения количества строк не поддерживаются. То есть, если ключевое слово OFFSET
указано в запросе, то перед ним должно быть ключевое слово LIMIT <N>
или FETCH NEXT <N> ROWS ONLY
. Обратного ограничения нет: ключевые слова LIMIT <N>
и FETCH NEXT <N> ROWS ONLY
можно использовать без OFFSET
.
Рекомендуется сочетать OFFSET
с ключевым словом ORDER BY
для получения упорядоченного набора строк. Ключевое слово ORDER BY
необязательно, однако без него запрос с OFFSET
возвращает неупорядоченный и потому непредсказуемый набор строк. Примеры запросов см. ниже.
Таким образом, для ключевого слова OFFSET
поддерживается следующий синтаксис:
[ ORDER BY <column_name> ]
{ LIMIT <value_1> | FETCH NEXT <value_1> ROWS ONLY }
OFFSET <value_2> [ ROW | ROWS ]
Ключевое слово ESTIMATE_ONLY
Ключевое слово ESTIMATE_ONLY
позволяет запросить информацию о выполнении запроса к данным, а не сами данные. То есть вместо выборки данных из таблицы или представления запрос возвращает следующую информацию:
- имя СУБД хранилища, в которой предполагается выполнение запроса;
- план выполнения запроса (только для ADB и ADP) — результат выполнения команды EXPLAIN в СУБД хранилища. Подробнее о команде EXPLAIN в ADB см. в документации Greenplum, о команде в ADP — в документации PostgreSQL;
- обогащенный запрос — запрос, подготовленный системой на основе исходного запроса с учетом специфики СУБД хранилища.
В ответе возвращается объект ResultSet с одной строкой, содержащей JSON-строку в следующем формате:
{
"plugin": "<имя_СУБД>",
"estimation": <план_выполнения_запроса>,
"query": <обогащенный_запрос>
}
Ниже показан пример JSON-строки, полученной по запросу к ADB. Для наглядности пример представлен в виде дерева, а не плоской строки.
{
"plugin": "ADB",
"estimation": [
{
"Plan": {
"Node Type": "Gather Motion",
"Senders": 4,
"Receivers": 1,
"Slice": 1,
"Segments": 4,
"Gang Type": "primary reader",
"Startup Cost": 0.00,
"Total Cost": 433.70,
"Plan Rows": 50000,
"Plan Width": 8,
"Plans": [
{
"Node Type": "Seq Scan",
"Parent Relationship": "Outer",
"Slice": 1,
"Segments": 4,
"Gang Type": "primary reader",
"Relation Name": "sales_actual",
"Alias": "sales_actual",
"Startup Cost": 0.00,
"Total Cost": 432.18,
"Plan Rows": 50000,
"Plan Width": 8
}
]
},
"Settings": {
"Optimizer": "Pivotal Optimizer (GPORCA)"
}
}
],
"query": "SELECT * FROM (SELECT id FROM sales.sales_actual WHERE sys_from <= 98 AND COALESCE(sys_to, 9223372036854775807) >= 98)"
}
Ниже показан пример JSON-строки, полученной по запросу к ADP. Для наглядности пример представлен в виде дерева, а не плоской строки.
{
"plugin": "ADP",
"estimation": [
{
"Plan": {
"Node Type": "Seq Scan",
"Parallel Aware": false,
"Relation Name": "sales_actual",
"Alias": "sales_actual",
"Startup Cost": 0.00,
"Total Cost": 18.80,
"Plan Rows": 880,
"Plan Width": 64
}
}
],
"query": "SELECT * FROM (SELECT id FROM sales.sales_actual WHERE sys_from <= 98 AND COALESCE(sys_to, 9223372036854775807) >= 98)"
}
Ограничения
- Запрос может обращаться либо к логической БД, либо к сервисной БД (см. SELECT FROM INFORMATION_SCHEMA), но не к обеим одновременно.
- Если ключами соединения в запросе выступают поля типа Nullable, то строки, где хотя бы один из ключей имеет значение NULL, не соединяются.
- Ключевое слово
ORDER BY
не поддерживается для SELECT-подзапроса в составе запроса CREATE MATERIALIZED VIEW.
Примеры
Звездочка и WHERE
Запрос с неявным указанием столбцов и ключевым словом WHERE
:
SELECT * FROM sales.sales
WHERE store_id = 1234
DATASOURCE_TYPE
Запрос с явным указанием столбцов и выбором данных из определенной СУБД хранилища (ADQM):
SELECT sold.store_id, sold.product_amount
FROM sales.stores_by_sold_products AS sold
DATASOURCE_TYPE = 'adqm'
GROUP BY, ORDER BY и LIMIT
Запрос с агрегацией, группировкой и сортировкой данных, а также выбором первых 20 строк:
SELECT s.store_id, SUM(s.product_units) AS product_amount
FROM sales.sales AS s
GROUP BY (s.store_id)
ORDER BY product_amount DESC
LIMIT 20
ESTIMATE_ONLY
Запрос на получение информации о запросе:
SELECT s.store_id, SUM(s.product_units) AS product_amount
FROM sales.sales AS s
GROUP BY (s.store_id)
ORDER BY product_amount DESC
ESTIMATE_ONLY
OFFSET
Запрос 20 строк, начиная с десятой:
SELECT * from sales.sales FETCH NEXT 20 ROWS ONLY OFFSET 9
ORDER BY, LIMIT и OFFSET
Запрос 20 строк, упорядоченных по значению id
и выбираемых начиная с десятой строки результата:
SELECT * from sales.sales ORDER BY id LIMIT 20 OFFSET 9
Такое сочетание ключевых слов позволяет выбирать данные порциями с сохранением их порядка.
FOR SYSTEM_TIME AS OF DELTA_NUM
Запрос записей, актуальных на момент закрытия дельты с номером 9, из материализованного представления:
SELECT * FROM sales.sales_and_stores FOR SYSTEM_TIME AS OF DELTA_NUM 9
Соединение таблиц из разных логических БД
Запрос с соединением данных двух логических таблиц из двух различных логических БД:
SELECT
st.id,
st.category,
s.product_code
FROM sales.stores FOR SYSTEM_TIME AS OF LATEST_UNCOMMITTED_DELTA AS st
INNER JOIN sales2.sales FOR SYSTEM_TIME AS OF LATEST_UNCOMMITTED_DELTA AS s
ON st.id = s.store_id
Соединение изменений из разных дельт
Запрос с соединением записей логической таблицы, добавленных и измененных в двух различных диапазонах дельт:
-- выбор логической базы данных sales в качестве базы данных по умолчанию
use sales
-- запрос данных из логической таблицы prices
SELECT
p1.product_code,
p1.price as feb_price,
p2.price as march_price,
(p2.price - p1.price) as diff
FROM
(SELECT product_code,
price from sales.prices
FOR SYSTEM_TIME STARTED IN(3,6)) AS p1
FULL JOIN (select product_code,
price from sales.prices
FOR SYSTEM_TIME STARTED IN(7,10)) AS p2
ON p1.product_code = p2.product_code
WHERE p1.product_code is NOT NULL
ORDER BY diff DESC
LIMIT 50
DATASOURCE_TYPE = 'adb'