如何找到连续缺席n天的人?

时间:2009-03-20 15:54:31

标签: sql sql-server sql-server-2005

数据库:MS SQL 2005

表:

  

EmployeeNumber | EntryDate |状态

示例数据:

200 | 3/1/2009 | P
200 | 2009年3月2日|一个
200 | 2009年3月3日|一个
201 | 3/1/2009 |一个
201 | 2009年3月2日| P

在存在P的情况下,A不存在。 我已尝试过row_number。但它不会产生我期望的序列。

对于上述数据,我期望的序列是 1 1 2 1 1

SELECT EmployeeNumber, EntryDate,Status
    ROW_NUMBER() OVER (
    PARTITION BY EmployeeNumber, Status
    ORDER BY EmployeeNumber,EntryDate    ) AS 'RowNumber'
    FROM [Attendance]

4 个答案:

答案 0 :(得分:3)

我不确定我是否按照1 1 2 1 1序列进行了您想要的操作,但只需在原始查询中添加一个订单即可生成该序列......

SELECT  EmployeeNumber, 
        EntryDate,
        Status,
        ROW_NUMBER() OVER (PARTITION BY EmployeeNumber, Status ORDER BY EmployeeNumber, EntryDate) AS 'RowNumber'    
FROM    Attendance
ORDER BY EmployeeNumber, EntryDate


/*
EmployeeNumber EntryDate               Status RowNumber
-------------- ----------------------- ------ --------------------
200            2009-03-01 00:00:00     P      1
200            2009-03-02 00:00:00     A      1
200            2009-03-03 00:00:00     A      2
201            2009-03-01 00:00:00     A      1
201            2009-03-02 00:00:00     P      1

(5 row(s) affected)
*/

答案 1 :(得分:1)

这对你有帮助吗? 它不会产生你问的序列(不知道怎么做),但它确实会让你连续几天没有人。

DECLARE @Attendance TABLE (EmployeeNumber INTEGER, EntryDate DATETIME, Status VARCHAR(1))

INSERT INTO @Attendance VALUES (200, '03/01/2009', 'P')
INSERT INTO @Attendance VALUES (200, '03/02/2009', 'A')
INSERT INTO @Attendance VALUES (200, '03/03/2009', 'A')
INSERT INTO @Attendance VALUES (200, '03/04/2009', 'A')
INSERT INTO @Attendance VALUES (200, '04/04/2009', 'A')
INSERT INTO @Attendance VALUES (200, '04/05/2009', 'A')
INSERT INTO @Attendance VALUES (201, '03/01/2009', 'A')
INSERT INTO @Attendance VALUES (201, '03/02/2009', 'A')
INSERT INTO @Attendance VALUES (201, '03/03/2009', 'P')


SELECT a1.EmployeeNumber, [Absent] = COUNT(*) + 1
FROM @Attendance a1
     INNER JOIN @Attendance a2 ON a1.EntryDate = a2.EntryDate - 1 
                                  AND a1.EmployeeNumber = a2.EmployeeNumber
                                  AND a1.Status = a2.Status
GROUP BY a1.EmployeeNumber

答案 2 :(得分:1)

您应该能够在SQL 2005中使用CTE执行此操作。窃取Lievens数据:

DECLARE @Attendance TABLE (EmployeeNumber INTEGER, EntryDate DATETIME, Status VARCHAR(1))

INSERT INTO @Attendance VALUES (200, '03/01/2009', 'P')
INSERT INTO @Attendance VALUES (200, '03/02/2009', 'A')
INSERT INTO @Attendance VALUES (200, '03/03/2009', 'A')
INSERT INTO @Attendance VALUES (200, '03/04/2009', 'A')
INSERT INTO @Attendance VALUES (200, '04/04/2009', 'A')
INSERT INTO @Attendance VALUES (200, '04/05/2009', 'A')
INSERT INTO @Attendance VALUES (201, '03/01/2009', 'A')
INSERT INTO @Attendance VALUES (201, '03/02/2009', 'A')
INSERT INTO @Attendance VALUES (201, '03/03/2009', 'P');

然后使用此CTE提取序列:


 WITH Dates 
    (
        EntryDate,
        EmployeeNumber,
        Status,
        Days
    ) 
    AS
    (
        SELECT
            a.EntryDate,
            a.EmployeeNumber,
            a.Status,
            1
        FROM
            @Attendance a

        WHERE
            a.EntryDate = (SELECT MIN(EntryDate) FROM @Attendance)


        -- RECURSIVE    
        UNION ALL

        SELECT
            a.EntryDate, 
            a.EmployeeNumber,
            a.Status,
            CASE WHEN (a.Status = Parent.Status) THEN Parent.Days + 1 ELSE 1 END
        FROM
            @Attendance a
        INNER JOIN
            Dates parent
        ON
            datediff(day, a.EntryDate, DateAdd(day, 1, parent.EntryDate)) = 0
        AND
            a.EmployeeNumber = parent.EmployeeNumber
    )

    SELECT * FROM Dates order by EmployeeNumber, EntryDate

虽然作为最后一点,序列对我来说确实很奇怪,但根据您的要求,可能有更好的方法来汇总数据?从来没有,这将产生您需要的序列

答案 3 :(得分:0)

你可以使用递归,类似于我所做的here。虽然你的问题似乎有点简单,而且由于SQL Server将递归限制为99,这对于那些缺席的人来说可能不起作用。让我考虑一下这几分钟。

如果你每天都有一排,请选择Lieven的加入。