Частичные возвраты в SQL: как найти заказ, которому вернули больше оплаты
Каждый возврат по отдельности меньше исходной оплаты, но вместе они превышают сумму заказа. Проверка отдельных строк не замечает такое нарушение. Сверять нужно накопленный факт возвратов с конкретным исходным платежом и его валютой.
Как разобрать ситуацию
В учебном наборе все суммы заданы в копейках одной валюты, а payment_id уникален. Сначала суммируем завершённые возвраты по платежу, затем сравниваем итог с исходной суммой. Неуспешные или отменённые попытки возврата в фактический денежный результат не входят. Полезно вывести и превышение: оператору важен размер расхождения.
Пример и ожидаемый результат
Оплата 1 равна 10000 копеек. По ней завершены возвраты 6000 и 5000. У оплаты 2 сумма 8000 и один возврат 2000. Нарушение только у первой: возвращено 11000, то есть превышение составляет 1000.
WITH pays(id,cents) AS(VALUES(1,10000),(2,8000)), refunds(pay_id,cents,status) AS(VALUES(1,6000,'done'),(1,5000,'done'),(2,2000,'done')), r AS(
SELECT pay_id,SUM(cents) refunded
FROM refunds
WHERE status='done'
GROUP BY pay_id)
SELECT p.id,p.cents,r.refunded,r.refunded-p.cents
FROM pays p
JOIN r ON r.pay_id=p.id
WHERE r.refunded>p.cents
ORDER BY p.id;Запрос возвращает платёж 1 с исходной суммой 10000, возвратами 11000 и превышением 1000. Это список для расследования, а не команда автоматического исправления денег.
Проверка перед применением
- Добавьте неуспешный возврат: он не должен увеличить фактический итог.
- Проверьте возврат без найденной исходной оплаты отдельным контролем связности.
- Проверьте повтор доставки одного refund_id: одинаковое денежное событие нельзя учитывать дважды.
Сохраните детализацию refund_id рядом с агрегатом, чтобы расследование не начиналось с повторного поиска всех строк. Для приёмки отчёта полезны три границы: возврат меньше оплаты, ровно равен и превышает её на одну копейку. Последний случай ловит ошибку округления и неверный знак сравнения.
Границы решения
У реального поставщика возможны отдельные корректировки, комиссии и валютные преобразования. Согласуйте правило сравнения с его контрактом. Отрицательные деньги нельзя автоматически обрезать: это уничтожит доказательство расхождения.
Если запросы уже пишутся, а уверенности в кардинальности, оконных рамках и проверке результата не хватает, продолжить практику можно в нашем платном курсе
Продвинутый SQL: сложные запросы и задачи для собеседований. Перед записью сравните программу со своей задачей и подготовкой.
Техническая справка: www.sqlite.org: документация, www.sqlite.org: документация.
Следующий шаг: Сложные SQL-запросы: разборы расчётов и ошибок. По смежным вопросам: Как разбить события на сессии в SQL по паузе между действиями, SQL: как найти двойное бронирование переговорной.
