Каждый день одно и то же. Открываешь клиент базы данных, чтобы что-то проверить, посчитать или найти. И снова пишешь почти тот же SELECT
, что и вчера, с тем же WHERE
и JOIN
. Знакомо?
SQL в большинстве случаях не требует сложные 100-строчные запросы с вложенными подзапросами на три уровня глубины. Чаще всего нам нужны простые, отточенные и, главное, эффективные конструкции.
В этой статье я собрал 7 таких запросов-«рабочих лошадок». Это не какой-то там справочник, а готовая шпаргалка для реальных задач.
Прежде чем перейти к запросам, запомните главное правило любого UPDATE или DELETE: всегда сначала пишите SELECT с теми же условиями WHERE.
Серьёзно, всегда. Это убережёт вас от случайного изменения или удаления не тех данных. Один мой знакомый в начале карьеры однажды чуть не отправил в архив несколько гигабайт production-данных из-за неверного условия. С тех пор он, да и я тоже делаем так:
-- Шаг 1: Сначала СМОТРИМ, что будем обновлять/удалять
SELECT * FROM orders WHERE status = 'test';
-- Шаг 2: Убедившись, что выборка корректна, заменяем на UPDATE/DELETE
DELETE FROM orders WHERE status = 'test';
Теперь, когда этот критически важный ритуал усвоен, перейдём к тем самым «рабочим лошадкам».
❯ 1. Ежедневный мониторинг
Как обычно, первым делом с утра нам нужно проверить, что система жива, данные поступают, ничего не сломалось ночью. Без ORDER BY
и LIMIT
можно случайно выгрузить всю таблицу и подвесить клиент, чего явно нам не хотелось бы.
SELECT id, status, created_at, amount
FROM latest_transactions
WHERE status = 'processed'
ORDER BY created_at DESC
LIMIT 10;
Ключевая привычка — всегда использовать ORDER BY
для детерминированности и LIMIT
для безопасности.
Допустим, вы увидели, что данные поступают. Что дальше? Обычно следом просят свестить итоги и подготовить отчет.
❯ 2. Агрегация данных
Самый частый запрос для любого отчёта. Посчитать количество, сумму, среднее значение по группам. Здесь на первый план выходят GROUP BY
и агрегатные функции.
SELECT
user_id,
COUNT(*) AS total_orders,
SUM(amount) AS total_revenue
FROM orders
WHERE created_at >= '2024-01-01'
GROUP BY user_id
HAVING SUM(amount) > 1000
ORDER BY total_revenue DESC;
Считает выручку по каждому пользователю с начала года, но показывает только «VIP-клиентов», принесших больше 1000 единиц. Запомните: WHERE
фильтрует строки догруппировки, а HAVING
— после.
Готовя отчеты, но вы вдруг замечаете аномалии: некоторые цифры не сходятся. Есть подозрение на дубликаты.
❯ 3. Охота за дубликатами
Дубликаты — вечная головная боль. Они появляются из-за ошибок в логике приложения, сбоев и багов. Их нужно уметь быстро находить. Спасет GROUP BY
и HAVING
.
SELECT
email,
COUNT(*) AS duplicate_count
FROM users
GROUP BY email
HAVING COUNT(*) > 1;
Находит все email-адреса, которые встречаются в таблице пользователей больше одного раза. Это отправная точка для «зачистки».
Дубликаты найдены. Чтобы принять осмысленное решение по ним, нужно больше информации. Пора заглянуть в связанные таблицы.
❯ 4. Объединение данных из нескольких таблиц
Данные в нормализованной базе всегда разбросаны. Чтобы получить полную картину, нужны JOIN
-ы.
SELECT
u.first_name,
u.last_name,
o.order_date,
o.total_amount,
p.product_name
FROM users u
INNER JOIN orders o ON u.id = o.user_id
LEFT JOIN products p ON o.product_id = p.id
WHERE u.country = 'Germany'
ORDER BY o.order_date DESC;
Главное — не запутаться в их типах.
Их всего 3:
INNER JOIN
— только совпадающие записи с обеих сторон
LEFT JOIN
— все записи из левой таблицы + совпадения справа
RIGHT JOIN
— все записи из правой таблицы + совпадения слева
Объединив данные, вы обнаруживаете сложную закономерность: нужно найти записи, которые соответствуют условию на основе других данных.
❯ 5. Запросы в запросах
Когда простых условий WHERE
уже недостаточно, на помощь приходят подзапросы. Они позволяют вложить один запрос в другой для сложной фильтрации.
SELECT *
FROM products
WHERE price > (
SELECT AVG(price)
FROM products
WHERE category_id = 5
)
AND category_id = 5;
Находит все товары в категории 5, цена которых выше средней по этой же категории. Идеально для поиска аномалий и выбросов.
Проанализировав данные, вы понимаете, что пора не просто смотреть, а что-то менять. Самое опасное — модификация данных.
❯ 6. Модификация данных с умом
Вот мы и дошли до самого опасного — UPDATE
и DELETE
. Здесь правило только одно: семь раз отмерь, один раз выполни. Всегда начинай с SELECT
.
-- ШАГ 1: Сначала смотрим, что будем менять
SELECT *
FROM users
WHERE last_login < '2024-01-01'
AND active = true;
-- ШАГ 2: Только затем выполняем UPDATE (и лучше в транзакции!)
BEGIN;
UPDATE users
SET active = false
WHERE last_login < '2024-01-01'
AND active = true;
-- Смотрим, что получилось, и только потом COMMIT или ROLLBACK
COMMIT;
Данные обновлены. Теперь нужно проанализировать результат в разрезе времени или групп, не схлопывая строки. Обычного GROUP BY
уже мало.
❯ 7. Оконные функции
Финальный аккорд — мощные оконные функции (OVER
, PARTITION BY
). Они позволяют делать агрегацию без группировки, сохраняя все исходные строки.
SELECT
product_id,
sale_date,
daily_revenue,
SUM(daily_revenue) OVER (
PARTITION BY product_id
ORDER BY sale_date
) AS cumulative_revenue
FROM sales
ORDER BY product_id, sale_date;
Для каждого товара рассчитывает нарастающий итог выручки по дням. В отличие от GROUP BY
, мы видим каждую продажу, а не только итог.
Вот и все. Этих 7 запросов хватит, чтобы уверенно чувствовать себя в 90% рабочих ситуаций с SQL. Они покрывают весь цикл работы с данными: от ежедневного мониторинга до сложной аналитики и аккуратной модификации.
Источник: https://habr.com/ru/companies/timeweb/articles/943298/