Как учесть только успешные платежи и открытые счета в SQL-запросе?
Что проверяют
Умеете ли вы писать проверочный запрос, который не врёт: выбрать правильный тип соединения, найти реальные значения статусов и не раздуть суммы дублями. Следом обычно просят вывести счета, по которым успешных платежей нет вовсе, или посчитать сумму по каждому счёту.
Как отвечать
Покажите, что сначала смотрите в данные, а потом пишете фильтр.
- значения статусов:
SELECT DISTINCT status FROM paymentsи то же для счетов. Успешный платёж в базе может называтьсяsuccess,SUCCEEDEDили быть кодом из справочника, а открытым счётом может считаться иactive, иfrozen. Если успешных статусов несколько, фильтр пишется черезIN; - простая выборка:
INNER JOINпоp.account_id = a.idи оба условия вWHERE. Остаются только пары «успешный платёж на открытом счёте»; - сумма по каждому открытому счёту:
FROM accounts a LEFT JOIN payments p ON p.account_id = a.id AND p.status = 'success' WHERE a.status = 'open', затемGROUP BY a.idиCOALESCE(SUM(p.amount), 0). Условие на платёж стоит вON, поэтому счета без платежей не пропадают и показывают 0; - NULL: строка с
status IS NULLне пройдёт ни= 'success', ни<> 'failed'. Если такой статус что-то значит, его учитывают явно.
Для тестировщика запрос это инструмент сверки. Хороший ответ заканчивается набором тестовых данных под него: платёж успешный, отклонённый, в обработке, возвращённый, счёт закрытый, счёт без платежей. По каждому случаю вы заранее знаете, попадёт ли он в выборку, и сравниваете это с тем, что показывает отчёт или API.
Где спотыкаются
Делают LEFT JOIN, а условие на платёж ставят в WHERE. Соединение фактически становится внутренним, и счета без успешных платежей исчезают из отчёта.
Пишут status <> 'failed' вместо перечисления успешных статусов. В выборку попадают платежи в обработке и возвраты, а новый статус, добавленный разработчиками, тихо сломает проверку.
Присоединяют ещё одну таблицу, например позиции счёта, и получают размножение строк: SUM удваивается, хотя каждый фильтр по отдельности верный.