Как настроить совокупный счет, сгруппированный по месяцам с базовыми условиями

#sql #sql-server

#sql #sql-сервер

Вопрос:

Я столкнулся с довольно интересным сценарием, в котором мне нужно объединить количество зарегистрированных пользователей и сгруппировать их по отдельному месяцу и всем последующим месяцам, предшествующим дате завершения. Начальный счетчик будет помещен в месяц, когда началась регистрация, и теперь мне нужно настроить накопительную сумму для выполнения единого подсчета.

Вот пара тестовых записей, с которыми я работаю введите описание изображения здесь

Я настроил следующий запрос для компиляции CTE date_month для компиляции полных 12 месяцев, полученных из моих переменных начального / конечного диапазона. Затем я присоединил его к своей тестовой таблице, чтобы установить места размещения счетчиков.

 DECLARE @EnrollmentDateStart DATETIME  = '2020-01-01'
DECLARE @EnrollmentDateEnd DATETIME  = '2020-12-01'

;WITH CTE_Months(year_month) AS 
(
  SELECT DATEADD(MONTH, n, DATEADD(MONTH, DATEDIFF(MONTH, 0, @EnrollmentDateStart), 0))
  FROM ( SELECT TOP (DATEDIFF(MONTH, @EnrollmentDateStart, @EnrollmentDateEnd)   1) 
    n = ROW_NUMBER() OVER (ORDER BY [object_id]) - 1
    FROM sys.all_objects ORDER BY [object_id] ) AS n
)
SELECT
  [Year]     = YEAR(cm.year_month),
  [Month]    = DATENAME(MONTH, cm.year_month), 
  SUM(IIF(tt.[Enrollment Start Date] >= @EnrollmentDateStart,1,0)) AS EnrollmentCount
FROM CTE_Months cm
    LEFT OUTER JOIN #TMP_Testing_Table tt
    ON tt.[Enrollment Start Date] >= cm.year_month
    AND tt.[Enrollment Start Date] < DATEADD(MONTH, 1, cm.year_month)
GROUP BY tt.Department, cm.year_month
  

На этом этапе я возвращаю следующие результаты, поэтому теперь у меня есть количество зачислений, помещенных в правильные начальные месяцы, полученные из даты начала регистрации.

введите описание изображения здесь

Теперь я пытаюсь выяснить, каков наилучший курс действий для размещения последующего подсчета за дополнительные месяцы, предшествующие дате завершения?

Например, первый пользователь (userId: 1) был зарегистрирован в марте 2020 года и завершен в августе 2020 года, поэтому, по сути, я хочу получить следующий результат, чтобы отразить количество месяцев в диапазоне от марта <> июля (последний месяц до завершения)

Январь: 0 Февраль: 0 Март: 1 Апрель: 1 Май: 1 Июнь: 1 Июль: 1 Август: 0 Сентябрь: 0 Октябрь: 0 Ноябрь: 0 Декабрь: 0

Однако, думая, что накопительный итог должен быть в состоянии охватить последующий за месяц диапазон по месяцам, мне тогда нужно было бы обнулить итог за все последующие месяцы до и после зарегистрированной даты завершения для этой записи, о которой идет речь.

Посмотрим, смогу ли я получить ваши мысли / предложения о том, как решить этот сценарий? Прошу прощения, если информация / объяснение сбивают с толку, но, пожалуйста, дайте мне знать, и я сделаю все возможное, чтобы уточнить.

Ответ №1:

 ....................    
SELECT
  [Year]     = YEAR(cm.year_month),
  [Month]    = DATENAME(MONTH, cm.year_month), 
  count(tt.userid) AS EnrollmentCount
FROM CTE_Months cm
    LEFT OUTER JOIN #TMP_Testing_Table tt on cm.year_month > eomonth([Enrollment Start Date], -1) 
           and cm.year_month <= tt.[Enrollment End Date]
GROUP BY cm.year_month
  

Комментарии:

1. Спасибо, скользящий счетчик вместе с функцией конца месяца работает отлично, однако я все еще разрабатываю несколько способов установить количество зачислений равным 0 для августа месяца (дата последнего зарегистрированного завершения) для одной регистрации.

2. @Curtis … я пропустил это. Вы могли бы попробовать EOMONTH() и для [Даты окончания]: EOMONTH([Дата окончания], если дата окончания в том же месяце, что и дата начала, тогда 0 еще -1)

3. Конечно, я тоже попробую. Я придумал способ поместить это во вложенный CTE, а затем применить вычисление минус, когда месяц регистрации == Месяц завершения для каждой записи. По большей части, предложение помогло мне, поэтому я отметил ваш как принятый ответ. Спасибо за вашу помощь в этом.