如何识别连续的工作日期?

时间:2017-03-01 12:40:25

标签: sql sql-server-2008-r2

我正在尝试编写一些将假期组合在一起的代码,并为每个分组创建一个唯一的ID。我遇到的麻烦是创建组以了解它们属于一起。

默认情况下,如果有人要求在5天内休息一周,则会获得特定ID(即223)。因此ID为223的假日实例为5天,我可以轻松获得开始和结束日期。

但如果有人决定预订周五休息(ID 224),然后请求周三和周四休息(ID 228),然后要求下周一休息(ID 230),那么我有3个单独的实例,实际上是一个假期,这里是我需要将他们聚在一起而忽略周末的地方。

我尝试了DENSE_RANK OVER PARTIONROW_NUMBER OVER ORDER的各种变体,但是我无法让它返回我需要的数字。

样本数据和所需的输出

SELECT '01-March-2017' AS HolidayDate, DATEPART(WK,'01-March-2017') AS Dw, 223 AS ID_Field, 1000 AS HolidayID
UNION ALL
SELECT '02-March-2017' AS HolidayDate, DATEPART(WK,'02-March-2017') AS Dw, 223, 1000
UNION ALL
SELECT '03-March-2017' AS HolidayDate, DATEPART(WK,'03-March-2017') AS Dw, 223, 1000
UNION ALL
SELECT '24-March-2017' AS HolidayDate, DATEPART(WK,'24-March-2017') AS Dw, 230 , 1001
UNION ALL
SELECT '27-March-2017' AS HolidayDate, DATEPART(WK,'27-March-2017') AS Dw, 235, 1001
UNION ALL
SELECT '20-Sep-2017' AS HolidayDate, DATEPART(WK,'20-Sep-2017') AS Dw, 224, 1002
UNION ALL
SELECT '27-Sep-2017' AS HolidayDate, DATEPART(WK,'27-Sep-2017') AS Dw, 228, 1003

因此,上面创建了一个示例,HolidayID是所需的列输出(随机选择的样本数)。 ID字段是提交假期请求时生成的数字。

正如您所见,223请求已完成且具有相同的ID,因此我可以选择MAX(日期)并通过ID_Field获得所需的结果分组。

230和235单独出现,但是假期相同(作为连续假期),所以我需要使用相同的ID对它们进行分组。

最后225个228是完全独立的请求,因此需要唯一的数字。

回答问题 - enter image description here

1 个答案:

答案 0 :(得分:2)

不支持LAG时

with    Holidays 
        as
        (
            select  row_number() over (order by HolidayDate)    as n
                   ,HolidayDate

            from    mytable
        )

select  h.HolidayDate

       ,count
        (
            case
                when    not
                        (
                            datediff (day,p.HolidayDate,h.holidayDate) = 1

                        or  (   datediff (day,p.HolidayDate,h.HolidayDate) = 3
                            and datename (dw,p.HolidayDate) = 'Friday'
                            )
                        )
                then    1
            end
        ) over (order by h.HolidayDate) + 1    as Holiday_id

from                Holidays    as h
        left join   Holidays    as p
        on          p.n = h.n - 1

order by h.HolidayDate

支持LAG时

select  HolidayDate
       ,count(is_gap) over (order by HolidayDate) + 1   as holiday_id

from   (select  HolidayDate

               ,case
                    when    not
                            (
                                datediff (day,prev_HolidayDate,HolidayDate) = 1

                            or  (   datediff (day,prev_HolidayDate,HolidayDate) = 3
                                and datename (dw,prev_HolidayDate) = 'Friday'
                                )
                            )
                    then    1
                end     as is_gap

        from   (select  HolidayDate
                       ,lag(HolidayDate) over (order by HolidayDate) as prev_HolidayDate

                from    mytable
                ) t
        ) t

order by HolidayDate
+-------------+------------+
| HolidayDate | holiday_id |
+-------------+------------+
| 2017-03-01  |          1 |
| 2017-03-02  |          1 |
| 2017-03-03  |          1 |
| 2017-03-24  |          2 |
| 2017-03-27  |          2 |
| 2017-09-20  |          3 |
| 2017-09-27  |          4 |
+-------------+------------+