Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
计算连续日期,不包括SQL中的周末_Sql_Sql Server - Fatal编程技术网

计算连续日期,不包括SQL中的周末

计算连续日期,不包括SQL中的周末,sql,sql-server,Sql,Sql Server,我正在编写一份缺勤报告,其中需要包括连续缺勤6次的员工,同时统计在给定日期范围内连续缺勤6次或以上的员工人数。我最大的问题是处理周末。因为这是一所学校,员工周一到周五工作,所以为了计算连续的6个日期,总是会有一个周末来分隔日期。我正在处理大量每天都会更新的数据,因此我无法将日期插入此任务的临时表中。我创建了一个临时表,用于存储开始日期和结束日期之间的所有日期,不包括周末: CREATE TABLE #TimeCardDates ( ClientID INT

我正在编写一份缺勤报告,其中需要包括连续缺勤6次的员工,同时统计在给定日期范围内连续缺勤6次或以上的员工人数。我最大的问题是处理周末。因为这是一所学校,员工周一到周五工作,所以为了计算连续的6个日期,总是会有一个周末来分隔日期。我正在处理大量每天都会更新的数据,因此我无法将日期插入此任务的临时表中。我创建了一个临时表,用于存储开始日期和结束日期之间的所有日期,不包括周末:

CREATE TABLE #TimeCardDates (
      ClientID          INT
    , EmpUID                BIGINT
    , BetweenDate           DATE
)

    ;WITH cte AS (
        SELECT 
              @StartDate StartDate
    UNION ALL
        SELECT 
              DATEADD(DAY, 1, StartDate)
        FROM cte
        WHERE StartDate < @EndDate
)
INSERT INTO #TimeCardDates (
      ClientID
    , EmpUID
    , BetweenDate
)
    SELECT 
          e.ClientID
        , e.EmpUID
        , c.StartDate
    FROM cte c
    CROSS JOIN (
        SELECT e.ClientID, e.EmpUID 
        FROM Employee e 
        JOIN #Clients c 
            ON c.ClientID = e.ClientID
    ) e

DELETE d
FROM #TimeCardDates d
    WHERE DATENAME(WEEKDAY, d.BetweenDate) IN ('Saturday','Sunday')
上述数据的预期结果:

 Employee3          Unscheduled Absence                        6

有人能帮我弄清楚怎么做吗?

要在两个日期(周末除外)之间生成日期,您可以执行以下操作

declare @startdate date,@enddate date
 set @startdate=cast('2020-02-01' as date)
 set @enddate=cast('2020-03-01' as date)

;with num_dates
   as (select row_number() over(order by name)-1 as rnk
        from master..spt_values
      )
select @startdate   
      ,dateadd(day,rnk,@startdate) as calendar_dates 
      ,rnk
  from num_dates
 where datepart(dw,dateadd(day,rnk,@startdate)) not in (6,7)
   and dateadd(day,rnk,@startdate) <=@enddate
这里有一个选项,使用lag检查前一天是否是连续缺勤。您可能可以将这些步骤合并到较少的CTE中,但我想将其编写出来,以便很容易看到逻辑是如何工作的

注意:我为雇员1添加了一些额外的测试数据,以确保它在6次以上的非连续缺勤中正常工作

create table #test (employee varchar(20), descr varchar(20), dateabsent date)

insert into #test --Create Sample Data
values
('Employee1','UnscheduledAbsence','2020-01-09'),
('Employee1','UnscheduledAbsence','2020-01-23'),
('Employee1','UnscheduledAbsence','2020-01-29'),
('Employee1','UnscheduledAbsence','2020-02-05'),
('Employee1','UnscheduledAbsence','2020-03-02'),
('Employee1','UnscheduledAbsence','2020-03-03'),
('Employee1','UnscheduledAbsence','2020-03-04'),
('Employee1','UnscheduledAbsence','2020-03-07'),
('Employee1','UnscheduledAbsence','2020-03-12'),
('Employee1','UnscheduledAbsence','2020-03-17'),
('Employee2','UnscheduledAbsence','2020-01-06'),
('Employee2','UnscheduledAbsence','2020-01-27'),
('Employee2','UnscheduledAbsence','2020-02-07'),
('Employee2','UnscheduledAbsence','2020-02-13'),
('Employee2','UnscheduledAbsence','2020-02-26'),
('Employee3','UnscheduledAbsence','2020-01-02'),
('Employee3','UnscheduledAbsence','2020-01-03'),
('Employee3','UnscheduledAbsence','2020-01-06'),
('Employee3','UnscheduledAbsence','2020-01-07'),
('Employee3','UnscheduledAbsence','2020-01-08'),
('Employee3','UnscheduledAbsence','2020-01-09')


; with CTE as (select *, datename(dw,dateabsent) as DW --Day of absence
from #test)

, cte2 as (select *
, case when lag(dateabsent) over (partition by employee order by dateabsent) = dateadd(day, -1, dateabsent) --if this absence immediately follows another absence
    or dw = 'Monday' and lag(dateabsent) over (partition by employee order by dateabsent) = dateadd(day, -3, dateabsent)  --or this is the Monday after a Friday absence
    then 1 else 0 end as Consecutive
from CTE)


, cte3 as (select *
    , sum(cte2.Consecutive) over (partition by employee order by dateabsent) + 1 as TotalConsecutiveAbsences --sum consecutive absences, add one for the current row absence
from cte2)

select cte3.employee, cte3.descr, cte3.TotalConsecutiveAbsences
from cte3
where cte3.TotalConsecutiveAbsences >= 6

编辑以稍微清理逻辑并添加注释

根据结果,您是否可以显示预期结果6个工作日转换为8个日历日,前提是在此期间没有其他节假日。你可以直接用8个日历日作为差额,这将使你的计算简单得多。如果我理解正确的话,你在问题中说你已经过滤掉了周末,把每个人放在一个只有工作日的临时表中,对吗?如果是这样的话,你可以使用存在的地方,使用间隔6天来检查。我知道这不能回答你的问题,但是这可以帮助确定哪两天是连续的,在两个日期之间,你应该考虑一个警告,我假设只有很多行作为开始日期和结束日期之间的最大差异。
create table #test (employee varchar(20), descr varchar(20), dateabsent date)

insert into #test --Create Sample Data
values
('Employee1','UnscheduledAbsence','2020-01-09'),
('Employee1','UnscheduledAbsence','2020-01-23'),
('Employee1','UnscheduledAbsence','2020-01-29'),
('Employee1','UnscheduledAbsence','2020-02-05'),
('Employee1','UnscheduledAbsence','2020-03-02'),
('Employee1','UnscheduledAbsence','2020-03-03'),
('Employee1','UnscheduledAbsence','2020-03-04'),
('Employee1','UnscheduledAbsence','2020-03-07'),
('Employee1','UnscheduledAbsence','2020-03-12'),
('Employee1','UnscheduledAbsence','2020-03-17'),
('Employee2','UnscheduledAbsence','2020-01-06'),
('Employee2','UnscheduledAbsence','2020-01-27'),
('Employee2','UnscheduledAbsence','2020-02-07'),
('Employee2','UnscheduledAbsence','2020-02-13'),
('Employee2','UnscheduledAbsence','2020-02-26'),
('Employee3','UnscheduledAbsence','2020-01-02'),
('Employee3','UnscheduledAbsence','2020-01-03'),
('Employee3','UnscheduledAbsence','2020-01-06'),
('Employee3','UnscheduledAbsence','2020-01-07'),
('Employee3','UnscheduledAbsence','2020-01-08'),
('Employee3','UnscheduledAbsence','2020-01-09')


; with CTE as (select *, datename(dw,dateabsent) as DW --Day of absence
from #test)

, cte2 as (select *
, case when lag(dateabsent) over (partition by employee order by dateabsent) = dateadd(day, -1, dateabsent) --if this absence immediately follows another absence
    or dw = 'Monday' and lag(dateabsent) over (partition by employee order by dateabsent) = dateadd(day, -3, dateabsent)  --or this is the Monday after a Friday absence
    then 1 else 0 end as Consecutive
from CTE)


, cte3 as (select *
    , sum(cte2.Consecutive) over (partition by employee order by dateabsent) + 1 as TotalConsecutiveAbsences --sum consecutive absences, add one for the current row absence
from cte2)

select cte3.employee, cte3.descr, cte3.TotalConsecutiveAbsences
from cte3
where cte3.TotalConsecutiveAbsences >= 6