Обзор команды SELECT
- Обзор
- Примеры использования
- Получение константного значения
- Получение всех столбцов таблицы
- Получение определенных столбцов таблицы
- Использование псевдонимов
- Использование функций и выражений
- Фильтрация данных
- Соединение таблиц
- Агрегирование данных
- Фильтрация агрегированных данных
- Сортировка данных
- Получение уникальных значений
- Ограничение возвращаемых данных
- Объединение результатов
- Использование подзапросов
- Общие табличные выражения (CTE)
- Оконные функции
Команда SELECT
позволяет получать строки из таблиц и представлений.
Она позволяет указать, данные из каких столбцов необходимо вернуть, применить фильтры и отсортировать вывод.
В СУБД Greengage, предназначенной для выполнения аналитических запросов, SELECT
является одной из наиболее часто используемых команд для исследования и анализа данных.
Обзор
Обзор синтаксиса
Упрощенный синтаксис команды SELECT
для получения строк из таблицы выглядит следующим образом:
SELECT [ * | <column> [, ...] ]
[FROM <table_name> [, ...]]
[WHERE <condition>]
где:
-
<column> [, …]
— имена одного или нескольких столбцов для выборки из таблицы или представления. Используйте*
, чтобы выбрать все столбцы. -
<table_name> [, …]
— имя одной или нескольких таблиц или представлений (при необходимости с указанием схемы), из которых производится выборка данных. -
<condition>
— выражение, используемое для фильтрации строк, возвращаемых SQL-запросом.
Команда SELECT
поддерживает множество дополнительных выражений для группировки, фильтрации и сортировки результатов:
[ WITH [ RECURSIVE ] <with_query> [, ...] ]
SELECT [ALL | DISTINCT [ON (<expression> [, ...])]]
* | <expression> [[AS] <output_name>] [, ...]
[FROM <from_item> [, ...]]
[WHERE <condition>]
[GROUP BY <grouping_element> [, ...]]
[HAVING <condition> [, ...]]
[WINDOW <window_name> AS (<window_definition>) [, ...]]
[{UNION | INTERSECT | EXCEPT} [ALL | DISTINCT] <select>]
[ORDER BY <expression> [ASC | DESC | USING <operator>] [NULLS {FIRST | LAST}] [, ...]]
[LIMIT {<count> | ALL}]
[OFFSET <start> [ROW | ROWS]]
[FETCH {FIRST | NEXT} [<count>] {ROW | ROWS} ONLY]
[FOR {UPDATE | NO KEY UPDATE | SHARE | KEY SHARE} [OF <table_name> [, ...]] [NOWAIT] [...]]
TABLE { [ONLY] <table_name> [*] | <with_query_name> }
Выполнение запроса SELECT
Последовательность обработки запроса SELECT
следующая:
-
WITH
Выполняются все запросы в выражении
WITH
. Фактически они служат временными таблицами, к которым можно обращаться в спискеFROM
. -
FROM
Вычисляются все элементы в списке
FROM
. Каждый элемент спискаFROM
— это реальная или виртуальная таблица, например, подзапрос или присоединенная таблица. Если в спискеFROM
указано несколько элементов, они объединяются перекрестным соединением (cross join). -
WHERE
Если указано выражение
WHERE
, из результата будут исключены все строки, не удовлетворяющие этому условию. -
GROUP BY
/HAVING
Если указано выражение
GROUP BY
или присутствуют вызовы агрегатных функций, вывод группируется по заданным ключам. Результаты агрегатных функций вычисляются для каждой группы. Если присутствует выражениеHAVING
, группы, не удовлетворяющие заданному условию, исключаются из вывода. -
Выражения в списке
SELECT
Результирующие строки формируются на основе выражений, перечисленных в списке
SELECT
. Выражения могут включать константы, ссылки на столбцы, вычисления, вызовы функций или оконные функции. -
DISTINCT
/DISTINCT ON
/ALL
Эти параметры определяют, следует ли удалять повторяющиеся строки из результата и каким образом это делать:
-
SELECT DISTINCT
исключает из результата повторяющиеся строки. -
SELECT DISTINCT ON
исключает строки, совпадающие по указанным выражениям. -
SELECT ALL
(по умолчанию) возвращает все строки результата, включая дубликаты.
-
-
UNION
/INTERSECT
/EXCEPT
С помощью операторов
UNION
,INTERSECT
иEXCEPT
можно объединять результаты нескольких запросовSELECT
в один результирующий набор. Каждый запрос должен возвращать одинаковое количество столбцов с совместимыми типами данных:-
Оператор
UNION
возвращает все строки, которые присутствуют хотя бы в одном из входных наборов. -
Оператор
INTERSECT
возвращает только те строки, которые присутствуют в обоих наборах. -
Оператор
EXCEPT
возвращает все строки, которые присутствуют в первом наборе, но отсутствуют во втором.
По умолчанию эти операторы удаляют повторяющиеся строки. Чтобы сохранить повторяющиеся строки, используйте ключевое слово
ALL
(например,UNION ALL
). Обратите внимание, что по умолчанию дляUNION
,INTERSECT
иEXCEPT
используетсяDISTINCT
, хотя дляSELECT
по умолчанию применяетсяALL
. -
-
ORDER BY
Если указано выражение
ORDER BY
, возвращаемые строки сортируются в заданном порядке. Если выражение не указано, порядок может быть произвольным и зависит от плана выполнения, выбранного СУБД. -
LIMIT
/OFFSET
/FETCH
Если указано выражение
LIMIT
,FETCH FIRST
илиOFFSET
, то операторSELECT
возвращает только часть результирующих строк. -
FOR UPDATE
/ …Если указано
FOR UPDATE
,FOR NO KEY UPDATE
,FOR SHARE
илиFOR KEY SHARE
, то операторSELECT
блокирует выбранные строки, предотвращая их изменение другими транзакциями.
Запросы, использующие ORDER BY
на больших наборах данных или DISTINCT
на большом числе полей, могут привести к созданию spill-файлов.
Узнайте больше в статье Управление spill-файлами.
Примеры использования
Получение константного значения
Команда SELECT
позволяет включать константы в результирующий набор.
Это значит, что можно выводить строки, числа или даты без обращения к столбцам таблиц.
Данная возможность может быть полезна для создания статических меток или возврата сообщений.
Следующий SQL-запрос выводит константное строковое значение и присваивает ему псевдоним:
SELECT 'Hello, world!' AS greeting;
Результат выглядит так:
greeting --------------- Hello, world! (1 row)
Получение всех столбцов таблицы
Чтобы получить все столбцы и строки из таблицы, используйте SELECT *
:
SELECT *
FROM categories;
Можно также использовать команду TABLE
:
TABLE categories;
Результат выглядит следующим образом:
category_code | name ---------------+------------- elec | Electronics cloth | Clothing home | Home (3 rows)
Если не указано выражение ORDER BY
, порядок строк в результатах запроса может быть произвольным.
Смотрите раздел Сортировка данных ниже.
Используйте SELECT *
с осторожностью для больших наборов данных: запрос обращается ко всем столбцам и может негативно влиять на производительность.
Получение определенных столбцов таблицы
Вместо того чтобы получить все столбцы с помощью SELECT *
, вы можете явно указать, какие столбцы возвращать.
Например, этот SQL-запрос возвращает только название товара и цену из таблицы products
:
SELECT name,
price
FROM products;
Вы также можете использовать полные имена столбцов, указав имя таблицы в качестве префикса:
SELECT products.name,
products.price
FROM products;
Это полезно в запросах с соединениями, где имена столбцов могут повторяться. Результат должен выглядеть так:
name | price --------------+--------- Coffee Maker | 85.00 T-Shirt | 25.00 Jacket | 60.00 Blender | 55.00 Laptop | 1200.00 Headphones | 150.00 Desk Chair | 200.00 Smartphone | 800.00 (8 rows)
Использование псевдонимов
Псевдонимы задают временные имена для столбцов или таблиц в запросах.
Вы можете переименовать столбцы в выводе с помощью ключевого слова AS
.
Это удобно, когда нужно дать столбцам более понятные имена, например:
SELECT name AS product_name,
price AS unit_price
FROM products;
Тот же запрос без использования AS
:
SELECT name product_name,
price unit_price
FROM products;
Результат выглядит следующим образом:
product_name | unit_price --------------+------------ Coffee Maker | 85.00 T-Shirt | 25.00 Jacket | 60.00 Blender | 55.00 Desk Chair | 200.00 Smartphone | 800.00 Laptop | 1200.00 Headphones | 150.00 (8 rows)
Также можно использовать ключевое слово AS
, чтобы указать псевдоним для таблицы:
SELECT p.name,
p.price
FROM products AS p;
Тот же запрос без использования AS
:
SELECT p.name,
p.price
FROM products p;
Использование функций и выражений
В команду SELECT
можно включать вызовы функций и выражения для вычисления или преобразования значений без изменения исходных данных.
-
Функция
UPPER()
преобразует названия товаров в верхний регистр:SELECT UPPER(name) AS product_name_caps, price FROM products;
Результат выглядит следующим образом:
product_name_caps | price -------------------+--------- COFFEE MAKER | 85.00 T-SHIRT | 25.00 JACKET | 60.00 BLENDER | 55.00 LAPTOP | 1200.00 DESK CHAIR | 200.00 SMARTPHONE | 800.00 HEADPHONES | 150.00 (8 rows)
-
Следующий запрос вычисляет цену каждого товара со скидкой 10%:
SELECT name, price, price * 0.9 AS discounted_price FROM products;
Результат выглядит так:
name | price | discounted_price --------------+---------+------------------ Coffee Maker | 85.00 | 76.500 T-Shirt | 25.00 | 22.500 Jacket | 60.00 | 54.000 Blender | 55.00 | 49.500 Desk Chair | 200.00 | 180.000 Smartphone | 800.00 | 720.000 Laptop | 1200.00 | 1080.000 Headphones | 150.00 | 135.000 (8 rows)
-
Выражение
CASE
позволяет возвращать разные значения в зависимости от условий:SELECT name, price, CASE WHEN price >= 500 THEN 'high' WHEN price >= 100 THEN 'medium' ELSE 'low' END AS price_level FROM products;
Результат выглядит так:
name | price | price_level --------------+---------+------------- Coffee Maker | 85.00 | low T-Shirt | 25.00 | low Jacket | 60.00 | low Blender | 55.00 | low Laptop | 1200.00 | high Desk Chair | 200.00 | medium Smartphone | 800.00 | high Headphones | 150.00 | medium (8 rows)
Фильтрация данных
Выражение WHERE
позволяет отфильтровать строки по заданным условиям.
Это помогает сузить результаты и получить только те данные, которые соответствуют определенным критериям.
Можно сравнивать значения, использовать поиск по шаблону и комбинировать несколько условий с помощью логических операторов AND
и OR
.
-
Используйте оператор равенства (
=
), чтобы найти строки, в которых значение столбца соответствует заданному значению:SELECT name, price FROM products WHERE name = 'Laptop';
Результат будет выглядеть так:
name | price --------+--------- Laptop | 1200.00 (1 row)
ПРИМЕЧАНИЕДля проверки значения на
NULL
используйте операторIS NULL
. -
Оператор
IN
позволяет сравнивать значение столбца со списком значений:SELECT name, price FROM products WHERE name IN ('Laptop', 'Smartphone');
Результат выглядит так:
name | price ------------+--------- Laptop | 1200.00 Smartphone | 800.00 (2 rows)
-
Оператор
LIKE
позволяет осуществлять поиск по шаблону с использованием подстановочных символов. Символ процента (%
) соответствует любой последовательности символов:SELECT name, price FROM products WHERE name LIKE '%phone%';
Результат выглядит так:
name | price ------------+-------- Smartphone | 800.00 Headphones | 150.00 (2 rows)
-
Можно комбинировать несколько условий с помощью
AND
иOR
, чтобы применить более детальные фильтры:SELECT name, price, stock FROM products WHERE price > 100 AND stock > 10;
Результат должен выглядеть так:
name | price | stock ------------+---------+------- Laptop | 1200.00 | 15 Smartphone | 800.00 | 30 Headphones | 150.00 | 40 (3 rows)
Соединение таблиц
Соединение таблиц позволяет объединять строки из двух или более таблиц на основе общего столбца.
Вы можете соединять таблицы, явно указывая условие соединения с помощью ключевого слова ON
.
В этом примере таблица products
соединяется с таблицей categories
по совпадению значений в столбцах category_code
:
SELECT products.name AS product_name,
categories.name AS category_name,
products.stock
FROM products
JOIN categories ON products.category_code = categories.category_code;
Если столбец, используемый для соединения, имеет одинаковое имя в обеих таблицах, можно использовать выражение USING
:
SELECT products.name AS product_name,
categories.name AS category_name,
products.stock
FROM products
JOIN categories USING (category_code);
Результат выглядит следующим образом:
product_name | category_name | stock --------------+---------------+------- Laptop | Electronics | 15 Desk Chair | Home | 10 Smartphone | Electronics | 30 Headphones | Electronics | 40 Coffee Maker | Home | 20 T-Shirt | Clothing | 100 Jacket | Clothing | 50 Blender | Home | 25 (8 rows)
Аналогично можно выполнить соединение более чем двух таблиц. Следующий SQL-запрос соединяет три таблицы и возвращает информацию о товаре, его категории и продажах:
SELECT products.name AS product_name,
categories.name AS category_name,
sales.quantity AS quantity_sold,
sales.date AS sale_date
FROM products
JOIN categories ON products.category_code = categories.category_code
JOIN sales ON products.id = sales.product_id;
Агрегирование данных
Агрегатные функции позволяют вычислять сводные значения, группируя строки по одному или нескольким столбцам.
К агрегатным функциям относятся SUM()
, COUNT()
, AVG()
, MIN()
и MAX()
.
В сочетании с GROUP BY
эти функции вычисляют агрегированные значения для каждой группы.
Следующие запросы вычисляют общее количество товаров для каждой категории, группируя строки по категориям и суммируя значения количества:
SELECT category_code,
SUM(stock) AS total_stock
FROM products
GROUP BY category_code;
Результат выглядит следующим образом:
category_code | total_stock ---------------+------------- home | 55 elec | 85 cloth | 150 (3 rows)
SELECT categories.name AS category_name,
SUM(products.stock) AS total_stock
FROM products
JOIN categories USING (category_code)
GROUP BY categories.name;
Результат выглядит следующим образом:
category_name | total_stock ---------------+------------- Home | 55 Clothing | 150 Electronics | 85 (3 rows)
Фильтрация агрегированных данных
Выражение HAVING
позволяет фильтровать группы после агрегации, аналогично тому, как WHERE
фильтрует отдельные строки до группировки.
Это полезно, когда нужно получить только те группы, которые соответствуют определенным условиям по итоговым значениям.
В следующих SQL-запросах показано, как использовать HAVING
для фильтрации категорий товаров с суммарным остатком, превышающим 80
:
SELECT category_code,
SUM(stock) AS total_stock
FROM products
GROUP BY category_code
HAVING SUM(stock) > 80;
Результат должен выглядеть следующим образом:
category_code | total_stock ---------------+------------- cloth | 150 elec | 85 (2 rows)
SELECT categories.name AS category_name,
SUM(products.stock) AS total_stock
FROM products
JOIN categories USING (category_code)
GROUP BY categories.name
HAVING SUM(products.stock) > 80;
Результат должен выглядеть следующим образом:
category_name | total_stock ---------------+------------- Clothing | 150 Electronics | 85 (2 rows)
Сортировка данных
После группировки и агрегирования данных можно использовать оператор ORDER BY
для сортировки результатов по агрегированному значению или по столбцу группировки.
Следующие запросы сортируют категории товаров по общему остатку в порядке убывания:
SELECT category_code,
SUM(stock) AS total_stock
FROM products p
GROUP BY category_code
ORDER BY total_stock DESC;
Результат выглядит так:
category_code | total_stock ---------------+------------- cloth | 150 elec | 85 home | 55 (3 rows)
SELECT categories.name AS category_name,
SUM(products.stock) AS total_stock
FROM products
JOIN categories USING (category_code)
GROUP BY categories.name
ORDER BY total_stock DESC;
Результат выглядит так:
category_name | total_stock ---------------+------------- Clothing | 150 Electronics | 85 Home | 55 (3 rows)
Получение уникальных значений
Ключевое слово DISTINCT
используется для возврата только уникальных значений из указанного столбца или комбинации столбцов.
Например, чтобы получить список уникальных категорий товаров из таблицы products
, выполните следующий запрос:
SELECT DISTINCT category_code
FROM products;
Результат должен выглядеть следующим образом:
category_code --------------- home elec cloth (3 rows)
Ограничение возвращаемых данных
Выражение LIMIT
ограничивает количество строк, возвращаемых SQL-запросом:
SELECT name,
price
FROM products
LIMIT 5;
Результат выглядит так:
name | price --------------+--------- Laptop | 1200.00 Coffee Maker | 85.00 T-Shirt | 25.00 Jacket | 60.00 Blender | 55.00 (5 rows)
Обратите внимание, что если использовать LIMIT
без ORDER BY
, порядок строк будет случайным и может меняться при повторных запросах.
Объединение результатов
Оператор UNION позволяет объединять результаты двух и более запросов SELECT
в один результирующий набор.
Следующий запрос разделяет товары на ценовые категории: low
для цен ниже 100 и high
для цен выше 500:
SELECT name,
price,
'low' AS price_level
FROM products
WHERE price < 100
UNION
SELECT name,
price,
'high' AS price_level
FROM products
WHERE price > 500;
Результат должен выглядеть следующим образом:
name | price | price_level --------------+---------+------------- Coffee Maker | 85.00 | low Blender | 55.00 | low Jacket | 60.00 | low Laptop | 1200.00 | high T-Shirt | 25.00 | low Smartphone | 800.00 | high (6 rows)
Использование подзапросов
Подзапрос — это запрос, вложенный в другой запрос.
Подзапросы можно использовать в выражениях SELECT
, FROM
и WHERE
для получения динамического значения или промежуточного результата, от которого зависит внешний запрос.
В этом примере используется подзапрос в выражении WHERE
для фильтрации товаров, цена которых выше средней цены всех товаров:
SELECT name,
price
FROM products
WHERE price > (SELECT AVG(price) FROM products);
Результат выглядит так:
name | price ------------+--------- Laptop | 1200.00 Smartphone | 800.00 (2 rows)
Общие табличные выражения (CTE)
Общие табличные выражения (Common Table Expression, CTE) позволяют определить временный набор результатов, который можно использовать в запросе SELECT
.
В следующем примере CTE с именем avg_price
вычисляет среднюю цену товара:
WITH avg_price AS (SELECT AVG(price) AS value FROM products)
SELECT name,
price
FROM products,
avg_price
WHERE price > avg_price.value;
Результат должен выглядеть следующим образом:
name | price ------------+--------- Laptop | 1200.00 Smartphone | 800.00 (2 rows)
Оконные функции
Оконные функции выполняют вычисления по набору строк, связанных с текущей строкой. Они часто используются для расчета накопительных итогов, ранжирования, скользящих средних и других накопительных операций.
Следующие запросы вычисляют накопительный итог по количеству для каждого product_id
с течением времени с помощью оконной функции SUM()
.
Окно определено так, что оно начинается заново для каждого товара и следует порядку дат продаж.
В данном запросе параметры окна задаются непосредственно внутри выражения OVER()
:
SELECT product_id,
date,
quantity,
SUM(quantity) OVER (PARTITION BY product_id ORDER BY date) AS running_total_quantity
FROM sales
WHERE product_id IN (1, 2)
ORDER BY product_id, date;
В этом запросе параметрам окна присваивается имя с помощью выражения WINDOW
:
SELECT product_id,
date,
quantity,
SUM(quantity) OVER w AS running_total_quantity
FROM sales
WHERE product_id IN (1, 2)
WINDOW w AS (PARTITION BY product_id ORDER BY date)
ORDER BY product_id, date;
Результат выглядит так:
product_id | date | quantity | running_total_quantity ------------+------------+----------+------------------------ 1 | 2025-01-03 | 1 | 1 1 | 2025-02-07 | 1 | 2 1 | 2025-03-15 | 1 | 3 2 | 2025-01-05 | 2 | 2 2 | 2025-02-01 | 1 | 3 2 | 2025-03-10 | 3 | 6 (6 rows)