Примеры запросов в SQL

Приветствую! Здесь вы наверняка найдете, что ищете. Примеры в лаборатории рассчитаны на то, что мы разбираем что-то конкретное.

Текущая статья посвящена sQL: SELECT, JOIN, агрегаты, CTE, оконные функции, DML и безопасные транзакции с пошаговыми примерами..

Поэтому за теорией по текущей теме вам — в энциклопедию. Если ещё не погружались, то маршрут прост:

  1. Основы
  2. Система и сеть
  3. Данные и разметка
  4. Код и разработка
  5. Языки
  6. Искусственный интеллект
  7. Проект
  8. Инфраструктура и безопасность
  9. Спин-офф

Обязательно пройдитесь.

А теперь приступим к нашему предмету.

Теория и соседние материалы

Термины

Термин Значение
SELECT Чтение данных
JOIN Соединение таблиц по ключу
GROUP BY Группировка для агрегатов
HAVING Фильтр после агрегации
CTE (WITH) Именованный подзапрос
Оконная функция Расчёт по «окну» строк без схлопывания

1. Базовая выборка и фильтр

SELECT id, name, salary
FROM employees
WHERE department_id = 10
  AND salary >= 50000
ORDER BY name ASC
LIMIT 20 OFFSET 0;

Шаги: укажите нужные столбцы (избегайте * в API) → WHEREORDER BY → пагинация.


2. JOIN и агрегаты

SELECT d.name AS department,
       COUNT(*) AS headcount,
       AVG(e.salary)::numeric(12,2) AS avg_salary
FROM employees e
INNER JOIN departments d ON d.id = e.department_id
WHERE e.hired_at >= DATE '2020-01-01'
GROUP BY d.name
HAVING COUNT(*) >= 5
ORDER BY headcount DESC;
  • INNER JOIN — только совпадающие строки.
  • LEFT JOIN — все из левой таблицы + совпадения справа.
  • HAVING фильтрует группы, WHERE — строки до группировки.

3. CTE и топ-N по группе

WITH ranked AS (
  SELECT e.*,
         ROW_NUMBER() OVER (
           PARTITION BY department_id
           ORDER BY salary DESC
         ) AS rn
  FROM employees e
)
SELECT id, name, department_id, salary
FROM ranked
WHERE rn <= 3;

ROW_NUMBER, RANK, DENSE_RANK — разные правила при равных значениях.


4. Подзапрос и EXISTS

SELECT c.id, c.name
FROM customers c
WHERE EXISTS (
  SELECT 1
  FROM orders o
  WHERE o.customer_id = c.id
    AND o.created_at >= CURRENT_DATE - INTERVAL '30 days'
);

EXISTS часто эффективнее большого IN на подзапросе.


5. Безопасное изменение (транзакция)


6. UPSERT (PostgreSQL)

INSERT INTO settings (key, value)
VALUES ('theme', 'dark')
ON CONFLICT (key) DO UPDATE
SET value = EXCLUDED.value;

Типичные ошибки

Ошибка Риск
UPDATE/DELETE без WHERE Потеря всех строк
SELECT * в проде Лишний трафик, хрупкость API
JOIN без индекса на ключе Медленные отчёты
Функция на столбце в WHERE Индекс не используется

Чек-лист

  • План запроса проверен (EXPLAIN / EXPLAIN ANALYZE).
  • DML в транзакции с проверкой результата.
  • Параметры через prepared statements, не конкатенация строк.