разбивая диапазон дат по месяцам - PullRequest
2 голосов
/ 07 июня 2011

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

Мне нужно разбить эти диапазоны дат по месяцам, но я не знаю, как это сделать.

Любое руководство приветствуется.

спасибо,

Ответы [ 2 ]

2 голосов
/ 08 июня 2011

Вы можете использовать таблицу чисел для этой задачи.

В приведенном ниже примере запроса системная таблица с именем master..spt_values используется вместо таблицы чисел:

SELECT
  CASE WHEN BeginDate > MonthStart THEN BeginDate ELSE MonthStart END AS BeginDate,
  CASE WHEN EndDate   < MonthEnd   THEN EndDate   ELSE MonthEnd   END AS EndDate,
  …  /* other columns as needed */
FROM (
  SELECT
    d.*,  /* or you could be more specific here */
    (
      DATEADD(month, DATEDIFF(month, 0, d.BeginDate) + v.number, 0)
    ) AS MonthStart,
    DATEADD(day, -1,
      DATEADD(month, DATEDIFF(month, 0, d.BeginDate) + v.number + 1, 0)
    ) AS MonthEnd
  FROM RowsOfData d
    INNER JOIN master..spt_values v ON v.type = 'P'
      AND v.number BETWEEN 0 AND DATEDIFF(month, d.BeginDate, d.EndDate)
) s

Каждая строка разбивается на серию строк, где BeginDate является либо фактическим BeginDate, либо началом месяца, в зависимости от того, какое значение больше, и аналогично для EndDate. Для иллюстрации следующие строки

BeginDate   EndDate
----------  ----------
2010-03-05  2010-03-24
2010-04-16  2010-05-05
2010-06-29  2006-08-12
2010-10-10  2011-02-01

разделится так:

BeginDate   EndDate
----------  ----------
2010-03-05  2010-03-24
2010-04-16  2010-04-30
2010-05-01  2010-05-05
2010-06-29  2010-06-30
2010-07-01  2010-07-31
2010-08-01  2010-08-12
2010-10-10  2010-10-31
2010-11-01  2010-11-30
2010-12-01  2010-12-31
2011-01-01  2011-01-31
2011-02-01  2011-02-02
1 голос
/ 08 июня 2011

Один из стандартных приемов - создать таблицу months, а затем выбрать все месяцы, пересекающие диапазон дат.

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

Это позволит вам взять один диапазон дат и получить набор диапазонов дат месяца. Затем вы можете присоединить этот запрос к своему набору данных и сгруппировать их по месяцам, чтобы разделить ваши данные по месяцам за диапазон месяцев. (Этот прием особенно полезен, когда некоторые периоды времени могут не иметь данных, но вы хотите, чтобы они отображались. Просто используйте левое соединение.)

...