如果他们有10天缺席,如何获得FromDate和ToDate?

时间:2016-07-13 05:24:39

标签: sql sql-server tsql

员工有10天缺席。

以下是我的数据。

我需要FromDate(the Date Start Absent)ToDate(the Date End Absent)

条件将是这样的

if the 10 days Continuous where STATUS='A' Included STATUS='R' 

供参考:

'A'缺席

'R'为RestDay

'L'为离开

    DECLARE @SomeTable TABLE ([EmpId] INT,[Date] DATETIME,[STATUS] char(1))

    --YOUR SAMPLE DATA
    INSERT INTO @SomeTable 
        ([EmpId],[Date],[STATUS])
    SELECT 999,'2016-07-11 00:00:00.000','A'
    UNION SELECT 999,'2016-07-10 00:00:00.000','A'
    UNION SELECT 999,'2016-07-09 00:00:00.000','R'
    UNION SELECT 999,'2016-07-08 00:00:00.000','R'
    UNION SELECT 999,'2016-07-07 00:00:00.000','A'
    UNION SELECT 999,'2016-07-06 00:00:00.000','A'
    UNION SELECT 999,'2016-07-05 00:00:00.000','A'
    UNION SELECT 999,'2016-07-04 00:00:00.000','A'
    UNION SELECT 999,'2016-07-03 00:00:00.000','A'
    UNION SELECT 999,'2016-07-02 00:00:00.000','R'
    UNION SELECT 999,'2016-07-01 00:00:00.000','R'
    UNION SELECT 999,'2016-06-30 00:00:00.000','A'
    UNION SELECT 999,'2016-06-29 00:00:00.000','A'
    UNION SELECT 999,'2016-06-28 00:00:00.000','A'
    UNION SELECT 999,'2016-06-27 00:00:00.000','L'
    UNION SELECT 999,'2016-06-26 00:00:00.000','A'
    UNION SELECT 999,'2016-06-25 00:00:00.000','R'

SELECT * FROM @SomeTable

我想得到以下输出:

EmpId   FromDate    ToDate
999 2016-06-28 00:00:00.000 2016-07-11 00:00:00.000

3 个答案:

答案 0 :(得分:3)

您可以使用以下查询:

SELECT EmpId, 
       MAX(CASE WHEN rn = 1 THEN [Date] END) AS FromDate,
       MAX(CASE WHEN rn = 10 THEN [Date] END) AS ToDate
FROM (
   SELECT EmpId, [Date], STATUS, grp,
          ROW_NUMBER() OVER (PARTITION BY EmpId, STATUS, grp 
                             ORDER BY [Date]) AS rn
   FROM (
      SELECT EmpId, [Date], STATUS,
             ROW_NUMBER() OVER (PARTITION BY EmpId ORDER BY [Date]) -
             ROW_NUMBER() OVER (PARTITION BY EmpId, STATUS 
                                ORDER BY [Date]) AS grp
      FROM @SomeTable
      WHERE STATUS <> 'R') AS t) AS s
GROUP BY EmpId, STATUS, grp
HAVING COUNT(*) >= 10

Demo here

修改

如果要求连续记录切片的总数等于或大于'A',则要求任意个连续10个记录,查询可以大大简化为:

SELECT EmpId, 
       MIN([Date]) AS FromDate,
       MAX([Date]) AS ToDate
FROM (
   SELECT EmpId, [Date], STATUS,
          ROW_NUMBER() OVER (PARTITION BY EmpId ORDER BY [Date]) -
          ROW_NUMBER() OVER (PARTITION BY EmpId, STATUS ORDER BY [Date]) AS grp
   FROM @SomeTable
   WHERE STATUS <> 'R') AS t
GROUP BY EmpId, STATUS, grp
HAVING COUNT(*) >= 10

答案 1 :(得分:0)

我不知道我是否完全理解,但我认为最简单的方法是计算STATUS A或R的出现次数。

以下查询列表计算10天后有多少非A-or-R 行。所有零行都有10天的差距。

SELECT *
      ,tbl.[Date]-10 AS TenDaysBack   
      ,(SELECT COUNT(*) 
        FROM @SomeTable AS x 
        WHERE x.EmpId=tbl.EmpId 
          AND x.[Date]>=tbl.[Date]-10 
          AND x.[Date]<=tbl.[Date] 
          AND x.STATUS NOT IN('A','R')
       )
FROM @SomeTable AS tbl
ORDER BY tbl.[Date]

答案 2 :(得分:0)

; with cte as
(
    SELECT  r = row_number() over (partition by EmpId order by Date),
        EmpId, Date, stat = case when STATUS in ('A', 'R') then 1 else 0 end
    FROM    @SomeTable t
),
cte2 as
(
    select  *, g = r - dense_rank() over (partition by stat order by r)
    from    cte
)
select  EmpId, FrDate = min(Date), ToDate = max(Date), Cnt = count(*)
from    cte2
where   stat    = 1
group by EmpId, g
having  count(*) >= 10