SQL для тестировщика: шпаргалка
Тестировщику не нужен весь SQL — нужен SELECT, чтобы проверить, что записалось в базу, найти тестовые данные и подтвердить дефект фактами, а не догадками. Это та часть, которую спрашивают на собеседовании и используют каждый день.
Порядок частей запроса
SELECT какие столбцы
FROM из какой таблицы
JOIN что присоединить
WHERE фильтр по строкам
GROUP BY чем группировать
HAVING фильтр по группам
ORDER BY сортировка
LIMIT сколько строк
Порядок жёсткий: WHERE не может стоять после GROUP BY.
А вот выполняется запрос иначе — сначала FROM, потом WHERE,
потом GROUP BY, и только в конце SELECT. Отсюда правило:
в WHERE нельзя ссылаться на псевдоним из SELECT, а в
ORDER BY — можно.
Выборка и фильтр
SELECT id, email, created_at
FROM users
WHERE status = 'active'
ORDER BY created_at DESC
LIMIT 20;
| Условие | Что делает |
|---|---|
= <> > < >= <= | Сравнение |
BETWEEN 10 AND 20 | Диапазон, границы включены |
IN ('new', 'paid') | Одно из перечисленного |
LIKE 'test%' | Начинается с «test»; % — любое число символов, _ — один |
IS NULL / IS NOT NULL | Проверка на пустоту |
WHERE phone = NULL не найдёт ничего, даже если пустых телефонов тысяча.
Сравнение с NULL всегда даёт «неизвестно». Нужно WHERE phone IS NULL.
Та же ловушка с <>: WHERE status <> 'paid' не вернёт
строки, где статус пуст.
JOIN — соединение таблиц
SELECT o.id, o.total, u.email
FROM orders o
JOIN users u ON u.id = o.user_id
WHERE o.created_at >= '2026-07-01';
| Вид | Что возвращает | Когда нужен тестировщику |
|---|---|---|
| INNER JOIN | Только совпавшие пары | Заказы вместе с их авторами |
| LEFT JOIN | Все строки левой таблицы, справа NULL если пары нет | Поиск сирот: заказы без пользователя, товары без картинки |
| RIGHT JOIN | Зеркально LEFT | Редко: обычно проще поменять таблицы местами |
| FULL JOIN | Всё с обеих сторон | Сверка двух источников данных |
Приём, который находит дефекты целостности:
SELECT o.id
FROM orders o
LEFT JOIN users u ON u.id = o.user_id
WHERE u.id IS NULL; -- заказы, чей пользователь удалён
Группировка и подсчёт
SELECT status, COUNT(*) AS cnt, SUM(total) AS revenue
FROM orders
WHERE created_at >= '2026-07-01'
GROUP BY status
HAVING COUNT(*) > 5
ORDER BY revenue DESC;
COUNT(*)считает строки,COUNT(col)— строки, где столбец не NULL. Разница между ними сама по себе диагностика.WHEREотсекает строки до группировки,HAVING— группы после.- Всё, что в
SELECTбез агрегата, должно быть вGROUP BY. COUNT(DISTINCT user_id)— сколько уникальных покупателей.
Задачи из реальной работы
Найти дубли по e-mail — проверка уникальности:
SELECT email, COUNT(*)
FROM users
GROUP BY email
HAVING COUNT(*) > 1;
Проверить, что заказ записался целиком — после прохождения сценария:
SELECT o.id, o.status, o.total, COUNT(i.id) AS items, SUM(i.price * i.qty) AS calc
FROM orders o
JOIN order_items i ON i.order_id = o.id
WHERE o.id = 10432
GROUP BY o.id, o.status, o.total;
Если total и calc разошлись — это дефект расчёта, и у вас
уже есть доказательство для репорта.
Подготовить тестовые данные — найти пользователя, у которого ровно то, что нужно:
SELECT u.id, u.email, COUNT(o.id) AS orders
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
GROUP BY u.id, u.email
HAVING COUNT(o.id) = 0; -- пользователи без единого заказа
Второй по величине заказ — любимый вопрос на собеседовании:
SELECT total FROM orders ORDER BY total DESC LIMIT 1 OFFSET 1;
Пять ошибок, на которых спотыкаются
= NULLвместоIS NULL.- Забыли условие в
JOIN— получили декартово произведение и «лишние» строки. - Столбец в
SELECTбез агрегата и безGROUP BY. LIKE '%text%'на большой таблице — запрос висит, индекс не работает.- Сравнение даты со временем:
created_at = '2026-07-01'не найдёт запись, созданную в 14:30. Нужен диапазон или приведение к дате.
UPDATE и DELETE без WHERE меняют всю таблицу.
Правило: сначала пишем SELECT с тем же WHERE, смотрим, какие
строки попали, и только потом (на тестовом стенде) превращаем в изменение. На проде
у тестировщика в норме доступ только на чтение.
Всё это можно прогнать прямо в браузере: SQL-тренажёр с учебной базой магазина — ваш запрос выполняется по-настоящему и сверяется с эталоном. Разбор с нуля — в открытом уроке SQL для тестировщика.
Это выжимка. Полный разбор — в курсе
В «Ручном тестировщике» 47 уроков и 36 тренажёров с проверкой результата. Часть уроков и четыре тренажёра открыты бесплатно.