Подписка на часть месяца: как посчитать пропорциональную сумму в 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 без деления на ноль и целочисленной ошибки.