计算连续几天,包括周末SQL Server

时间:2018-03-15 16:03:35

标签: sql sql-server tsql

我有一个连续几天的SQL查询,但我需要它来计算周末。例如,如果有人星期五和星期一休息,我需要连续2天计算,如果这是有道理的。

表:

CREATE TABLE Absence(
Date Date,
Code varchar(10),
Name varchar(10),
Type varchar(10)
);

INSERT INTO Absence (Date, Code, Name, Type)
VALUES ('01-10-18', 'S', 'Sam', 'Sick'),
('01-11-18','S', 'Sam', 'Sick'),
('01-12-18','S', 'Sam', 'Sick'),
('01-21-18','S', 'Sam', 'Sick'),
('01-26-18','S', 'Sam', 'Sick'),
('01-27-18','S', 'Sam', 'Sick'),
('02-12-18','S', 'Sam', 'Holiday'),
('02-13-18','S', 'Sam', 'Holiday'),
('02-18-18','S', 'Sam', 'Holiday'),
('02-25-18','S', 'Sam', 'Holiday'),
('02-10-18','S', 'Sam', 'Holiday'),
('02-13-18','F', 'Fred', 'Sick'),
('02-14-18','F', 'Fred', 'Sick'),
('03-09-18','F', 'Fred', 'Sick'),
('03-12-18','F', 'Fred', 'Sick'),
('02-28-18','F', 'Fred', 'Sick');

我有这段代码:

select name, min(date), max(date), count(*) as numdays, type
from (select a.*,
         row_number() over (partition by name, type order by date) as 
seqnum_ct
  from absence a
 ) a
group by name, type, dateadd(day, -seqnum_ct, date);

它产生了这个结果:

| name |            |            | numdays |    type |
|------|------------|------------|---------|---------|
| Fred | 2018-02-13 | 2018-02-14 |       2 |    Sick |
| Fred | 2018-02-28 | 2018-02-28 |       1 |    Sick |
| Fred | 2018-03-09 | 2018-03-09 |       1 |    Sick |
| Fred | 2018-03-12 | 2018-03-12 |       1 |    Sick |
|  Sam | 2018-02-10 | 2018-02-10 |       1 | Holiday |
|  Sam | 2018-02-12 | 2018-02-13 |       2 | Holiday |
|  Sam | 2018-02-18 | 2018-02-18 |       1 | Holiday |
|  Sam | 2018-02-25 | 2018-02-25 |       1 | Holiday |
|  Sam | 2018-01-10 | 2018-01-12 |       3 |    Sick |
|  Sam | 2018-01-21 | 2018-01-21 |       1 |    Sick |
|  Sam | 2018-01-26 | 2018-01-27 |       2 |    Sick |

如果你看一下这些行

('03-09-18','F', 'Fred', 'Sick'),
('03-12-18','F', 'Fred', 'Sick'),

这应该等于连续1个周期,即使它是星期五和星期一,如果这是有道理的。如何编辑此代码以使其包含周末?

由于

SQL小提琴 - http://sqlfiddle.com/#!18/1de27/1

2 个答案:

答案 0 :(得分:1)

试试这个:

select name, min(date), max(date), count(*) as numdays, type
from (
    select date, code, name, type, seqnum_ct + sum(weekend) over (partition by name, type order by date) seqnum_ct
    from (select a.*,
             row_number() over (partition by name, type order by date) as seqnum_ct,
             case when datepart(weekday, [date]) = 2 and 
                       datepart(weekday, lag([date]) over (partition by name, type order by date)) = 6 then 2 else 0 end [weekend]
      from #absence a
     ) a
 ) a
group by name, type, dateadd(day, -seqnum_ct, date);

答案 1 :(得分:0)

您可以使用运行总和来创建组来处理周末。您需要检查的是当前行的工作日是2(星期一),前一行是6(星期五),对于给定的名称,按日期顺序键入。

select name, min(date), max(date), count(*) as numdays, type
from (select a.*,sum(col) over(partition by Name,type order by [Date]) as grp
      from (select a.*,
            case when datediff(day,lag([Date]) over(partition by Name,type order by [Date]),[Date])=1 or
            (datepart(weekday,[Date])=2 and datepart(weekday,lag([Date]) over(partition by Name,type order by [Date]))=6)
            then 0 else 1 end as col
            from absence a
           ) a
     ) a
group by name, type, grp