事务方向Row Over Partition操作

时间:2013-05-07 07:59:19

标签: sql sql-server tsql

我有时间和出勤时钟系统的交易数据,我必须计算区域中的总小时数。所以我使用row over partition创建了一个查询来执行此操作。

如果用户正确使用他们的时钟卡(意味着方向遵循例如in,out,in,out..etc),它可以正常工作。但是因为我们总是不能依赖用户这样做,我们得到这样的数据:

MSTSQ   DATE        DIRECTION   TIME
-----   ----------  ---------   ------------
61      2013-03-12  IN          07:56:43.000
61      2013-03-12  OUT         09:58:19.000
61      2013-03-12  IN          10:16:05.000
61      2013-03-12  OUT         12:08:10.000
61      2013-03-12  OUT         12:08:11.000
61      2013-03-12  IN          12:08:11.000
61      2013-03-12  IN          12:11:04.000
61      2013-03-12  OUT         13:45:28.000
61      2013-03-12  IN          13:45:29.000
61      2013-03-12  IN          13:50:38.000
61      2013-03-12  OUT         16:28:11.000
61      2013-03-12  IN          16:28:12.000

我的sql语句如下:

WITH TIME_LIST
AS(
SELECT ROW_NUMBER() OVER (PARTITION BY TD.MSTSQ, TD.DATE ORDER BY TD.ID) RN
        , TD.MSTSQ
        , TD.DATE
        , TD.DIRECTION
        , TD.TIME
FROM TRANSACK_DETAILS TD
)

Select 
  currul.MSTSQ
, currul.DATE
, Convert(datetime, prevul.TIME - currul.TIME,108) [Time In Zone]
FROM TRANSACTIONS 
INNER JOIN TIME_LIST currul ON currul.MSTSQ = TRANSACTIONS.MST_SQ  
    AND TRANSACTIONS.EVENT_DATE = currul.DATE
INNER JOIN TIME_LIST prevul ON currul.MSTSQ = prevul.MSTSQ 
    AND currul.DATE = prevul.DATE AND currul.Rn+1 = prevul.Rn

我的结果如下:

MSTSQ   DATE        Time In Zone
-----   --------    ------------
61      20130312    02:01:36.000
61      20130312    00:17:46.000
61      20130312    01:52:05.000
61      20130312    00:00:01.000
61      20130312    00:00:00.000
61      20130312    00:02:53.000
61      20130312    01:34:24.000
61      20130312    00:00:01.000
61      20130312    00:05:09.000
61      20130312    02:37:33.000
61      20130312    00:00:01.000

现在我需要将语句更改为仅计算IN和OUT(Time In Zone)方向之间的时间。

关于如何做到这一点的任何想法?

提前致谢

1 个答案:

答案 0 :(得分:1)

select tin.MSTSQ
  , [DATE] = tin.[DATE]
  , INTIME = tin.[TIME]
  , OUTTIME = tout.[TIME]
  , DURATION = datediff(ss, tin.[TIME], tout.[TIME])
from times tin
  outer apply (select top 1 *
              from times tout
              where tin.MSTSQ = tout.MSTSQ
                and tin.[DATE] = tout.[DATE]
                and tin.[TIME] < tout.[TIME]
              order by tout.[TIME]) tout
where tin.DIRECTION = 'IN'
  and (tout.DIRECTION IS NULL or tout.DIRECTION = 'OUT')
order by tin.MSTSQ

SQL Fiddle with demo

这是一种做法。我已经猜到了如何处理丢失的数据,但可以根据需要进行更新。

我理解这可能是伪表名,但是可能值得注意的是,使用保留的T-SQL单词是不好的形式,如果可能的话你应该考虑组合日期和时间列。