Как написать SQL-запрос для вывода клиентов с средней суммой платежей больше 2000 рублей?
Что проверяют
Понимаете ли вы разницу между WHERE и HAVING и умеете ли фильтровать по агрегату. Для тестировщика следом идёт второй слой: как вы проверите, что запрос считает правильно, и какие данные для этого подготовите.
Как отвечать
Сначала уточните схему: где лежат платежи, есть ли статус, нужны ли имена клиентов. Типичный ответ:
SELECT c.id, c.name, AVG(p.amount) AS avg_amount
FROM clients c
JOIN payments p ON p.client_id = c.id
WHERE p.status = 'success'
GROUP BY c.id, c.name
HAVING AVG(p.amount) > 2000;Проговорите порядок выполнения: WHERE отбирает строки до группировки, поэтому AVG в нём использовать нельзя; GROUP BY собирает платежи клиента в группу; HAVING отсекает группы по уже посчитанному среднему.
Нюансы, которые отличают сильный ответ:
- NULL:
AVGпропускает строки сNULLвamount, среднее считается только по заполненным; - тип результата: в SQL Server
AVGпо целочисленной колонке возвращает целое и отбрасывает дробную часть, в PostgreSQL результат будетnumeric. На границе в 2000 это меняет ответ; - алиас в
HAVING: MySQL разрешает написатьHAVING avg_amount > 2000, PostgreSQL нет, там повторяют выражение; - единицы: суммы часто хранят в копейках, тогда условие превращается в
> 200000.
И обязательно скажите, как проверите запрос. Тестовые клиенты по граничным значениям: со средним ровно 2000 (не должен попасть, условие строгое), 2000.01 и 1999.99, с одним платежом, с NULL в сумме, с возвратом на отрицательную сумму, с неуспешными платежами, которые должны отфильтроваться.
Где спотыкаются
Пишут WHERE AVG(amount) > 2000. База вернёт ошибку, и это самая частая осечка на таком вопросе.
Путают среднее по клиенту с условием на каждый платёж: WHERE amount > 2000 отберёт крупные платежи, а не клиентов с большим средним.
Не спрашивают про статусы и возвраты. Запрос синтаксически верный, но считает отменённые платежи, и тестировщик, который этого не заметил, пропустил дефект.