разбивка диапазона дат по месяцам

#sql #sybase

#sql #sybase

Вопрос:

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

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

приветствуются любые рекомендации.

Спасибо,

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

1. Итак, если дата начала и дата окончания относятся к двум разным месяцам, как вы хотите это представить? Два разных значения, по одному для каждого месяца? Просто дата начала? Просто конечная дата? Среднее значение двух дат?

2. мне нужно разделить каждый из них по соответствующему месяцу, поэтому, если, например, это 13 июня — 18 июля, то это должно быть, например, 13 июня — 30 июня, 01 июля — 18 июля

3. Ваш вопрос слишком привязан к вашему контексту, чтобы быть полезным кому-либо еще. Это также довольно расплывчато. Пожалуйста, перефразируйте это и предоставьте информацию об используемых вами инструментах, о том, что вы уже пробовали, пример входных данных и желаемые выходные данные.

Ответ №1:

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

В приведенном ниже примере запроса системная таблица с именем 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
  

Ответ №2:

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

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

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