На странице заказа написано «Оплачено». А действительно ли сохранилась нужная сумма? Не появился ли заказ дважды? На такие вопросы помогает ответить SQL — язык запросов к базе данных.
Начнём с чтения готовых данных. Устанавливать PostgreSQL, писать сервер или создавать большую учебную базу для этой статьи не нужно. Если у вас пока нет учебной базы, сначала разберите примеры на бумаге, затем попробуйте наш SQL-тренажёр. Таблицы в тренажёре могут отличаться от примера ниже.
Таблица похожа на лист с данными
Таблица хранит записи одного вида. Строка — отдельная запись, столбец — её свойство.
Представим таблицу orders — заказы:
id
customer_id
status
total
101
7
paid
1200
102
8
new
800
103
7
paid
500
id — номер заказа, customer_id — номер покупателя, status — состояние заказа, total — сумма в рублях. В нашем примере paid означает «оплачен», а new — «новый».
Все результаты ниже разобраны по этой маленькой таблице. Это учебные примеры, а не отчёт о запуске запросов в вашей базе.
1. Найти конкретный заказ
SELECT id, status, total
FROM orders
WHERE id = 101;
Читаем по порядку:
SELECT — какие столбцы показать: номер, статус и сумму.
FROM orders — откуда взять данные: из таблицы заказов.
WHERE id = 101 — оставить только заказ с номером 101.
Результат: одна строка — заказ 101, статус paid, сумма 1200.
Для QA это полезно после действия в интерфейсе: создайте заказ, запишите его номер и найдите именно его. Просто «последняя запись» ненадёжна — параллельно заказ мог создать другой человек.
2. Отобрать нужные записи
SELECT id, total
FROM orders
WHERE status = 'paid'
ORDER BY total DESC;
WHERE отбирает оплаченные заказы. Текстовое значение пишем в одинарных кавычках. ORDER BY total DESC располагает суммы от большей к меньшей.
Результат: сначала заказ 101 с суммой 1200, затем заказ 103 с суммой 500. Для порядка от меньшего к большему используют ASC.
Что можно проверить: интерфейс показывает те же оплаченные заказы и такой же порядок? Убедитесь, что на сайте и в запросе выбраны одинаковые условия и данные не изменились между проверками.
3. Посчитать записи и сумму
SELECT COUNT(*) AS orders_count, SUM(total) AS total_sum
FROM orders
WHERE status = 'paid';
COUNT(*) считает строки. SUM(total) складывает суммы. AS даёт результату понятное название.
Результат: 2 оплаченных заказа на общую сумму 1700.
Не путайте эти вопросы: «Сколько заказов?» и «Сколько денег?». Два заказа по 500 рублей — это две записи и сумма 1000.
Количество строк до и после действия — только подсказка. Чтобы доказать создание нужного заказа, найдите его по номеру и сверьте поля.
4. Найти незаполненное значение
NULL означает, что значение отсутствует или неизвестно. Это не ноль и не пустой текст.
Представим таблицу users с полями id и email. Чтобы найти пользователей без записанного email:
SELECT id, email
FROM users
WHERE email IS NULL;
Здесь нужна конструкция IS NULL, а не = NULL.
Если система также допускает пустую строку, это другая проверка: email = ''. Сначала узнайте, как продукт хранит незаполненное поле и обязательно ли оно вообще. Отсутствующий email не всегда является багом.
5. Найти повторы
SELECT email, COUNT(*) AS copies
FROM users
WHERE email IS NOT NULL
GROUP BY email
HAVING COUNT(*) > 1;
Запрос собирает пользователей с одинаковым email в группы (GROUP BY), считает записи и оставляет группы, где записей больше одной (HAVING).
Например, две записи с test@example.com дадут этот email и число 2. Это повод проверить правило регистрации: если один email должен принадлежать только одному аккаунту, найдено нарушение. Учёт регистра и пробелов — отдельные правила продукта.
6. Связать две таблицы
Сведения о покупателе обычно лежат отдельно от заказа. Допустим, таблица users содержит id и name, а у покупателя 7 имя Анна.
SELECT o.id, u.name, o.total
FROM orders o
JOIN users u ON u.id = o.customer_id
WHERE o.id = 101;
JOIN соединяет связанные записи. Условие u.id = o.customer_id говорит: номер пользователя должен совпасть с номером покупателя в заказе. o и u — короткие обозначения таблиц, чтобы не писать их полные имена каждый раз.
Результат при этих условиях: заказ 101, Анна, сумма 1200.
Обычный JOIN покажет только совпавшие записи. А если у одного заказа несколько позиций, соединение с позициями даст несколько строк на заказ. Поэтому после JOIN нельзя бездумно суммировать всё подряд: можно посчитать одну сумму несколько раз. К сложным соединениям стоит вернуться после освоения простых запросов.
Как применять это в работе
Узнайте, в какой таблице сохраняется результат действия.
Выполните действие на учебном или тестовом стенде.
Найдите запись по её номеру или уникальному тестовому признаку.
Сверьте нужные поля с требованиями: статус, сумму, владельца.
Зафиксируйте номер записи и обнаруженное расхождение в баге.
Список полей и названия таблиц спросите у команды. Подключение к другой среде, задержка обновления или неверно выбранный заказ могут создать ложное впечатление бага.
С чего начинать безопасно
На первых порах достаточно SELECT — чтения данных. Команды UPDATE, DELETE и DROP изменяют или удаляют данные, для этой статьи они не нужны. Изучайте их позже в отдельной учебной базе.
Синтаксис разных баз немного отличается. Примеры здесь используют обычные конструкции, поддерживаемые PostgreSQL; названия таблиц учебные. Если запрос не выполнился, сначала проверьте схему и используемую базу, а не меняйте данные наугад.
Попробуйте сами
По таблице из начала статьи ответьте: сколько заказов у покупателя 7 и какова их общая сумма?
Разбор: заказы 101 и 103, всего два, сумма 1700. В запросах из пунктов 2 и 3 замените условие на customer_id = 7. Сначала предскажите результат, потом сравните с ответом учебной базы.