SELECT

Содержание раздела
  1. Синтаксис
    1. Поддерживаемые ключевые слова
    2. Ключевое слово FOR SYSTEM_TIME
    3. Поддерживаемые типы соединений (префиксы JOIN)
    4. Ключевое слово OFFSET
    5. Ключевое слово ESTIMATE_ONLY
  2. Ограничения
  3. Примеры
    1. Звездочка и WHERE
    2. DATASOURCE_TYPE
    3. GROUP BY, ORDER BY и LIMIT
    4. ESTIMATE_ONLY
    5. OFFSET
    6. ORDER BY, LIMIT и OFFSET
    7. FOR SYSTEM_TIME AS OF DELTA_NUM
    8. Соединение таблиц из разных логических БД
    9. Соединение изменений из разных дельт

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

Запрос обрабатывается в порядке, описанном в разделе Порядок обработки запросов на чтение данных. В ответе возвращается:

  • объект 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.

Поддерживаемые ключевые слова

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

  1. FOR SYSTEM_TIME — для указания момента времени или периода, за который выбираются данные или изменения данных. Если ключевое слово не указано, из логической таблицы и логического представления выбираются данные, актуальные на момент обработки запроса, из материализованного представления — данные, актуальные на момент последней синхронизации представления. Описание синтаксиса см. в секции Ключевое слово FOR SYSTEM_TIME;
  2. JOIN ON — для соединения данных нескольких логических таблиц и (или) представлений из одной или нескольких логических БД. Возможные префиксы см. в секции Возможные типы соединений (префиксы JOIN);
  3. WHERE — для указания условий выбора данных;
  4. GROUP BY — для группировки данных;
  5. HAVING — для указания условий выбора сгруппированных данных;
  6. ORDER BY — для сортировки данных;
  7. LIMIT или FETCH NEXT <N> ROWS ONLY— для ограничения количества возвращаемых строк;
  8. OFFSET — для пропуска указанного количества строк в результате запроса. Описание синтаксиса см. в секции Ключевое слово OFFSET;
  9. DATASOURCE_TYPE — для указания СУБД хранилища, из которой выбираются данные;
  10. 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'