找出相同列的行之间的差异(时间数据之间的差异)

时间:2013-07-15 06:56:17

标签: asp.net sql sql-server datetime time

我想找到同一员工组中同一列的时间数据之间的差异。我写了一个查询如下:

WITH    rows AS
        (
        SELECT  isnull(left(hhmm,2)+ ':'+ right(left(hhmm,4),2),'''') as login,
         ROW_NUMBER() OVER (ORDER BY cardno) AS rn
        FROM    ATTN01072013_copy13_7_13 
        )
SELECT  *--mc.login-mp.login as diff
FROM    rows mc
JOIN    rows mp
ON      mc.rn = mp.rn - 1 

此查询将返回如下数据:

cardno  login   rn  cardno  login   rn
E44920  09:18   1   E44920  09:46   2
E44920  09:46   2   E44920  17:09   3
E44920  17:09   3   E44920  16:57   4
E44920  16:57   4   E44920  17:34   5
E44920  17:34   5   E44920  17:53   6
E44920  17:53   6   E44920  17:56   7
E44920  17:56   7   E44920  17:57   8
E44920  17:57   8   E44920  18:00   9

现在我想找到第1和第2次登录时间之间的差异..然后第3和第4次登录时间。我怎么能这样做,请尽快建议解决方案,谢谢。

3 个答案:

答案 0 :(得分:2)

解决方案:

DECLARE @Event TABLE(
    EventID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    CardNo VARCHAR(10) NOT NULL,
    [Login] DATETIME NOT NULL
    -- To prevent duplicate events
    -- This constraint will create an index used to optimize the RowNum and the last queries
    UNIQUE(CardNo,[Login]) 
);

INSERT INTO @Event(CardNo,[Login])
            SELECT 'E44920', '2013-07-15T09:18:00'
UNION ALL   SELECT 'E44920', '2013-07-15T09:46:00'
UNION ALL   SELECT 'E44920', '2013-07-15T17:09:00'
UNION ALL   SELECT 'E44920', '2013-07-15T16:57:00'
UNION ALL   SELECT 'E44920', '2013-07-15T17:34:00'
UNION ALL   SELECT 'E44920', '2013-07-15T17:53:00';

DECLARE @EventWithRowNum TABLE(
    RowNum INT NOT NULL,
    CardNo VARCHAR(10) NOT NULL,
    PRIMARY KEY (CardNo,RowNum),
    [Login] DATETIME NOT NULL
    UNIQUE(CardNo,[Login])
);
INSERT INTO @EventWithRowNum (CardNo,[Login],RowNum)
SELECT  e.CardNo, e.[Login], ROW_NUMBER() OVER(PARTITION BY e.CardNo ORDER BY e.[Login]) AS RowNum
FROM    @Event e;

-- Final query
SELECT  crt.RowNum,
        crt.CardNo, 
        crt.[Login] AS CurrentLogin,
        nxt.RowNum,
        nxt.[Login] AS NextLogin,
        DATEDIFF(SECOND, crt.Login, nxt.Login) AS Diff_Seconds
FROM    @EventWithRowNum crt -- crt = odd rows
LEFT JOIN @EventWithRowNum nxt ON crt.CardNo=nxt.CardNo AND crt.RowNum=nxt.RowNum-1 -- nxt = even rows
WHERE   crt.RowNum % 2 = 1 -- odd rows; you could add a computed column Modulo2 AS (RowNum % 2) PERSISTED and then you could define a index (key: Modulo2, CardNo, Login)
ORDER BY crt.CardNo, crt.[Login];

结果:

RowNum      CardNo     Current_Login           RowNum      Next_Login              Diff_Seconds
----------- ---------- ----------------------- ----------- ----------------------- ------------
1           E44920     2013-07-15 09:18:00.000 2           2013-07-15 09:46:00.000 1680
3           E44920     2013-07-15 16:57:00.000 4           2013-07-15 17:09:00.000 720
5           E44920     2013-07-15 17:34:00.000 6           2013-07-15 17:53:00.000 1140

答案 1 :(得分:0)

尝试:

DATEDIFF (mi, CAST(mc.login AS DATETIME), CAST(mp.login AS DATETIME)) as diff

这会在几分钟内产生差异

SQLFiddle DEMO

答案 2 :(得分:0)

以下是您可以尝试使用的完整查询。正如Nenad Zivkovic已经表明的那样,想法是使用DATEDIFF函数。

唯一不同的是,我建议使用完整日期时间计算差异,以避免在一次登录如22:03而另一次登记为00:16时可能出现的问题。

WITH    rows AS
    (
    SELECT  isnull(left(hhmm,2)+ ':'+ right(left(hhmm,4),2),'''') as login,
    hhmm as Full_Login,
     ROW_NUMBER() OVER (ORDER BY cardno) AS rn
    FROM    ATTN01072013_copy13_7_13 
    )
SELECT  mc.login, 
   mc.rn,
   DATEDIFF(mi,mc.Full_Login, mp.Full_Login)
   mp.login,
   mc.rn      
FROM    rows mc
JOIN    rows mp
ON      mc.rn = mp.rn