Подписка на часть месяца: как посчитать пропорциональную сумму в SQL
Подписка начала действовать в середине октября, а отчёт начислил полную месячную стоимость. Для пропорционального расчёта нужно пересечь период активности с отчётным месяцем и выбрать правило количества оплачиваемых дней.
Как разобрать ситуацию
В примере цена за месяц равна 3100 рублям, а расчёт ведётся по календарным дням конкретного месяца. Периоды полуоткрытые: start включается, end исключается. Октябрь имеет 31 день. Активность с 11 октября до 1 ноября занимает 21 день, поэтому расчётная сумма составляет 2100 рублей. Это согласованная учебная тарификация, а не стандарт всех подписочных сервисов.
Пример и ожидаемый результат
Сначала найдём пересечение активности и месяца, затем разделим его длительность на длительность месяца. При отсутствии пересечения сумма равна нулю. В производственном расчёте округляйте деньги по явному правилу и только в согласованный момент.
WITH x(start_d,end_d,month_start,month_end,price) AS(VALUES('2026-10-11','2026-11-01','2026-10-01','2026-11-01',3100)), d AS(
SELECT MAX(0,julianday(MIN(end_d,month_end))-julianday(MAX(start_d,month_start))) active,julianday(month_end)-julianday(month_start) days,price
FROM x)
SELECT CAST(active AS INT),ROUND(price*active/days,2)
FROM d;Запрос возвращает 21 день активности и сумму 2100. При сдвиге начала на 1 октября результат должен стать полным месячным тарифом.
Проверка перед применением
- Проверьте начало подписки ровно в первый день следующего месяца: начисления за текущий быть не должно.
- Сравните февраль и октябрь, если используется фактическое число дней.
- Определите, как учитываются приостановка, бесплатный период и смена тарифа внутри месяца.
Перед использованием отчёта попросите владельца продукта вручную посчитать один неполный месяц по договору. Если договор говорит о другом способе начисления, SQL должен отражать именно его. Красивое деление по календарю не делает неверно выбранную бизнес-модель правильной.
Границы решения
Это не универсальное определение MRR и не инструкция по бухгалтерскому признанию выручки. Почасовая тарификация, фиксированные тридцатидневные периоды и налоги требуют другой модели. Синтаксис date и julianday относится к SQLite.
Если запросы уже пишутся, а уверенности в кардинальности, оконных рамках и проверке результата не хватает, продолжить практику можно в нашем платном курсе
Продвинутый SQL: сложные запросы и задачи для собеседований. Перед записью сравните программу со своей задачей и подготовкой.
Техническая справка: www.sqlite.org: документация, www.sqlite.org: документация.
Следующий шаг: Сложные SQL-запросы: разборы расчётов и ошибок. По смежным вопросам: Как разбить события на сессии в SQL по паузе между действиями, Конверсия в SQL без деления на ноль и целочисленной ошибки.
