SQL для аналитика: первые запросы за полчаса
За полчаса вы соберёте небольшую таблицу заказов и научитесь выбирать строки, фильтровать даты, считать выручку и связывать заказы с клиентами. Примеры рассчитаны на PostgreSQL 16 и запускаются в одном SQL-сеансе.

За полчаса вы соберёте небольшую таблицу заказов и научитесь выбирать строки, фильтровать даты, считать выручку и связывать заказы с клиентами. Примеры рассчитаны на PostgreSQL 16: в конце вы получите запрос, который покажет сумму оплаченных заказов по каждому клиенту.
Перед началом
Понадобятся сервер PostgreSQL 16 и SQL-клиент: например, psql, DBeaver или редактор запросов в вашей аналитической платформе. Нужен доступ, который позволяет выполнять SQL-команды. Учебный пример создаёт временные таблицы: запускайте его в отдельной сессии, не в рабочей базе с данными компании.
Запросы ниже выполняйте по порядку и в одном подключении. Временные таблицы доступны только в этой сессии и исчезнут, когда вы отключитесь. Если у вас другая СУБД, синтаксис дат и создания временных таблиц может отличаться.
Шесть шагов от таблицы к отчёту
- Создайте учебные данные. Выполните блок целиком. В нём две таблицы: клиенты и заказы.
CREATE TEMP TABLE customers ( customer_id integer PRIMARY KEY, customer_name text NOT NULL ); INSERT INTO customers (customer_id, customer_name) VALUES (1, 'Анна'), (2, 'Борис'), (3, 'Вера'); CREATE TEMP TABLE orders ( order_id integer PRIMARY KEY, customer_id integer NOT NULL, order_date date NOT NULL, amount numeric(10, 2) NOT NULL, status text NOT NULL ); INSERT INTO orders (order_id, customer_id, order_date, amount, status) VALUES (101, 1, '2025-01-10', 1200.00, 'paid'), (102, 2, '2025-01-11', 800.00, 'paid'), (103, 1, '2025-01-14', 500.00, 'cancelled'), (104, 3, '2025-02-02', 2400.00, 'paid'), (105, 2, '2025-02-05', 700.00, 'paid');Проверка: выполните
SELECT COUNT(*) FROM orders;. Результат — 5. Если запускаете весь блок повторно, сначала удалите временные таблицы или создайте новое подключение: таблицы с такими именами уже существуют в текущей сессии. - Выберите нужные столбцы.
SELECTзадаёт, что показать, аFROM— из какой таблицы читать.SELECT order_id, order_date, amount FROM orders;Не начинайте с
SELECT *в рабочем отчёте: запрос вернёт все столбцы, в том числе ненужные, и результат сложнее проверять. Проверка: в выдаче пять строк и три столбца — номер, дата и сумма заказа. - Отфильтруйте строки условием. Например, найдите оплаченные заказы за январь. Правая граница диапазона — первое число следующего месяца; так условие не зависит от времени внутри даты.
SELECT order_id, order_date, amount FROM orders WHERE status = 'paid' AND order_date >= DATE '2025-01-01' AND order_date < DATE '2025-02-01';Проверка: запрос возвращает два заказа на 1200 и 800. Строка со статусом
cancelledне попадает в результат. Текстовые значения статуса заключайте в одинарные кавычки. - Отсортируйте выдачу. Без
ORDER BYбаза не обещает вернуть строки в ожидаемом порядке. Для списка заказов по убыванию суммы используйте:SELECT order_id, order_date, amount FROM orders WHERE status = 'paid' ORDER BY amount DESC LIMIT 3;DESCставит большие суммы первыми, аLIMIT 3оставляет три строки. Проверка: первой идёт сумма 2400, последней — 800. Если равные значения должны идти в определённом порядке, добавьте второе поле сортировки, напримерorder_id. - Посчитайте итог по группам. Агрегатные функции считают значения по строкам, а
GROUP BYсобирает строки в группы. Здесь считаем количество заказов и сумму по статусу.SELECT status, COUNT(*) AS order_count, SUM(amount) AS total_amount FROM orders GROUP BY status ORDER BY status;Проверка: для
paidрезультат — 4 заказа и 5100; дляcancelled— 1 заказ и 500. Если добавите вSELECTобычный столбец, его обычно нужно включить и вGROUP BY. - Свяжите заказы с клиентами. В обеих таблицах есть
customer_id— по нему и выполняетсяJOIN. Сначала оставьте только оплаченные заказы, затем сгруппируйте их по имени.SELECT c.customer_name, COUNT(*) AS paid_orders, SUM(o.amount) AS paid_total FROM customers AS c JOIN orders AS o ON o.customer_id = c.customer_id WHERE o.status = 'paid' GROUP BY c.customer_id, c.customer_name ORDER BY paid_total DESC;Проверка: в результате три клиента: Вера — 2400, Борис — 1500, Анна — 1200. Сумма по всем строкам — 5100, как в предыдущем шаге. Если итог не сходится, проверьте условие связи и фильтр по статусу.
Термин. JOIN — операция, которая соединяет строки из таблиц по условию. В этом примере заказ получает имя клиента из таблицы customers благодаря совпадению идентификаторов.
Хороший аналитический запрос не просто выдаёт цифру: его результат можно проверить на знакомом примере и объяснить, какие строки в него попали.
Если запрос не сработал
ERROR: relation "orders" does not exist. Таблица не создана в этой сессии или запрос выполняется в другом подключении. Повторите шаг 1 в том же SQL-редакторе и проверьте, что команды завершились без ошибки.ERROR: column "amount" does not exist. В имени столбца опечатка или выбранная таблица устроена иначе. Сверьте его с блоком создания таблицы; в реальной базе проверьте схему через интерфейс SQL-клиента.ERROR: column "orders.status" must appear in the GROUP BY clause or be used in an aggregate function. В запросе с группировкой вы выбрали поле, которое не агрегируется и не включено вGROUP BY. Добавьте его в группировку или уберите из результата.- Запрос вернул ноль строк. Ошибки синтаксиса нет, но фильтр не совпал с данными. Проверьте написание статуса, границы дат и то, что даты в тестовом наборе относятся к указанному периоду.
Что делать дальше
Возьмите знакомую аналитическую задачу и сформулируйте её до написания SQL: какие строки нужны, за какой период и по каким группам считать итог. Затем двигайтесь в порядке FROM → WHERE → GROUP BY → ORDER BY и сверяйте сумму с независимым подсчётом.
На следующем шаге разберите LEFT JOIN и значения NULL: они важны, когда в отчёте должны остаться клиенты без заказов. Перед запуском тяжёлого запроса на рабочей базе проверьте план выполнения средствами вашего SQL-клиента и уточните у команды, какие ограничения действуют на чтение данных.
IT-архитектор / SQL-оптимизатор: Поиск N+1, оптимизация запросов, code review, поиск багов.
Спросить за 20 ₽Источники: PostgreSQL 16: руководство по SQL, PostgreSQL 16: SELECT
Частые вопросы
Можно ли выполнять примеры не в PostgreSQL?
Что делать, если у меня другая версия PostgreSQL?
Нужно ли знать программирование, чтобы начать писать SQL?
Почему сумма в моём отчёте может оказаться больше ожидаемой?
Можно ли запускать учебные запросы на рабочей базе?
Как не перепутать дату и время в отчёте?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.