1

I have transactional data from our Time and Attendance Clocking system that I have to calculate the total Hours in zone with. So I created a query using row over partition to do this.

It works fine if the users use their clock cards correctly (meaning the directions follow e.g. in,out,in,out..etc). But because we cant always rely on the user to do that we get data like this:

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

My sql statement works as follow:

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

My result then looks like this:

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

Now I need to change the statement to only calculate the time between the IN and OUT (Time In Zone) Directions.

Any ideas on how to do this?

Thanks in advance

4

1 回答 1

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 与演示

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

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

于 2013-05-07T08:33:02.160 回答