#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 и конца месяца.
Это позволит вам взять один диапазон дат и получить набор диапазонов дат за месяц. Затем вы можете присоединить этот запрос к своему набору данных и сгруппировать по месяцам, чтобы ваши данные были разделены по месяцам в течение ряда месяцев. (Этот прием особенно полезен, когда в некоторых периодах времени могут отсутствовать данные, но вы хотите, чтобы они отображались. Просто используйте левое соединение.)