TSQL - SQL 2008 - в диапазоне дат (от начальной даты до конечной даты) можно ли разбить этот диапазон на отдельные строки по выходным (и исключая)?

Прошу прощения за плохо сформулированный заголовок, мне дали задание, выходящее за рамки моих ограниченных навыков, и я надеялся, что кто-то может помочь.

У нас есть сотрудники, у которых есть графики 24/7 для бронирования работы и выездных заданий (в том числе и на выходных), но это не относится к отпуску. Из-за этого мне было поручено разбить единый диапазон дат по выходным (и исключить их).

Например:

Дата начала: 30 апреля 2015 г. Дата окончания: 13 мая 2015 г.

30/04/2015, 01/05/2015
04/05/2015, 05/05/2015, 06/05/2015, 07/05/2015, 08/05/2015,
11/05/2015, 12/05/2015, 13/05/2015,

Примечание. Выходные были исключены, а диапазон дат разделен на три за три недели.

Желательно: укажите начальную и конечную точки для каждого диапазона, как показано ниже.

30/04/2015 - 01/05/2015 --(the same as it is the start and end dates)
04/05/2015 - 08/05/2015
11/05/2015 - 13/05/2015

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

Мы используем приложение базы данных TSQL на SQL 2008.

Большое спасибо.


person Hiigara    schedule 13.05.2015    source источник
comment
Спасибо за редактирование, Стефан   -  person Hiigara    schedule 13.05.2015


Ответы (2)


Спасибо за интересную задачу. Примечание: я использую стандартный формат даты, но концепция та же.

DECLARE @StartDate  DATE = '20150430',  --April 30, 2015
        @EndDate    DATE = '20150513';  --May 13,2015

WITH CTE_Dates
AS
(
    SELECT @StartDate dates
    UNION ALL
    SELECT DATEADD(DAY,1,dates)
    FROM CTE_Dates
    WHERE dates < @EndDate
),
CTE_weeks
AS
(
    SELECT  dates,
            DATEPART(WEEK,dates) WeekID
    FROM CTE_Dates
    WHERE DATENAME(WEEKDAY,dates) NOT IN ('Saturday','Sunday') --doesn't include weekends
)

SELECT  WeekID,
        MIN(dates) StartDate,
        MAX(dates) EndDate,
        STUFF(list_dates,1,1,'') list
FROM CTE_weeks A
CROSS APPLY (
                SELECT ',' + CAST(dates AS VARCHAR(100))
                FROM CTE_weeks B
                WHERE A.WeekID = B.WeekID
                ORDER BY dates
                FOR XML PATH('')
            ) CA(list_dates)
GROUP BY WeekID,STUFF(list_dates,1,1,'')

Полученные результаты:

WeekID      StartDate  EndDate    list
----------- ---------- ---------- ------------------------------------------------------------
18          2015-04-30 2015-05-01 2015-04-30,2015-05-01
19          2015-05-04 2015-05-08 2015-05-04,2015-05-05,2015-05-06,2015-05-07,2015-05-08
20          2015-05-11 2015-05-13 2015-05-11,2015-05-12,2015-05-13
person Stephan    schedule 13.05.2015
comment
Я думаю, вы предполагаете здесь конкретную DATEFIRST настройку - нет гарантии, какие weekday значения являются выходными. Например. SET DATEFIRST 4; SELECT DATEPART(weekday,'20150509') возвращает 3. - person Damien_The_Unbeliever; 13.05.2015
comment
Вы правы, поэтому я изменил его на DATENAME. - person Stephan; 13.05.2015
comment
Это просто переключает проблему на то, какие языковые настройки действуют для пользователя. - person Damien_The_Unbeliever; 13.05.2015
comment
Спасибо за помощь! - person Hiigara; 14.05.2015

Кажется, это работает. Предполагается, что вы указали дату начала в будний день:

declare @StartDate datetime = '20150430'
declare @EndDate datetime = '20150513'

; With Ord as (
    select @StartDate as StartAt,@StartDate as EndAt
    union all
    select StartAt,DATEADD(day,1,EndAt)
    from Ord where DATEPART(weekday,EndAt) != DATEPART(weekday,'20150710') --Known Friday
    and EndAt < @EndDate
    union all
    select DATEADD(day,3,EndAt),DATEADD(day,3,EndAt)
    from Ord where DATEPART(weekday,EndAt) = DATEPART(weekday,'20150710') --Still known Friday
    and DATEADD(day,3,EndAt) <= @EndDate
)
select StartAt,MAX(EndAt) as EndAt
from Ord
group by StartAt

Результат:

StartAt                 EndAt
----------------------- -----------------------
2015-04-30 00:00:00.000 2015-05-01 00:00:00.000
2015-05-04 00:00:00.000 2015-05-08 00:00:00.000
2015-05-11 00:00:00.000 2015-05-13 00:00:00.000

Я сравниваю DATEPART, используя «известный товар» (т. Е. Я просто случайно выбранный из календаря) Пятница, так что этот код работает для любых DATEFIRST настроек.

person Damien_The_Unbeliever    schedule 13.05.2015
comment
всегда рад выслушать отзывы, анонимный противник. - person Damien_The_Unbeliever; 13.05.2015
comment
Конечно, это был не я, большое спасибо за ваше время и усилия, это очень помогло мне в выполнении моей задачи. +1 - person Hiigara; 13.05.2015