2008-11-09 93 views
0

我正在写一个简单的时间跟踪程序来管理我自己的项目。我非常喜欢将报告代码保存在数据库中,所以我一直在尝试创建一些生成发票和时间表的sprocs。我该如何计算check in和check out列表中的timespans?

我有一个表,其中包含时钟操作,IE“Punch In “和”冲出“。它还包含执行此操作的用户,与操作关联的项目和当前日期/时间。

我可以从此表中选择为特定时间/项目/和用户获取时钟,但我想将它聚合,以便每个时钟输入和输出都从2行转换为包含总时间的单个行。

例如,这里是一个示例输出:

ClockActionID  ActionType DateTime 
-------------------- ---------- ----------------------- 
17     1   2008-11-08 18:33:56.000 
18     2   2008-11-08 18:33:59.587 
19     1   2008-11-08 18:34:01.023 
20     2   2008-11-08 18:34:02.037 
21     1   2008-11-08 18:45:06.317 
22     2   2008-11-08 18:46:14.597 
23     1   2008-11-08 18:46:16.283 
24     2   2008-11-08 18:46:17.173 
25     1   2008-11-08 18:50:37.830 
26     2   2008-11-08 18:50:39.737 
27     1   2008-11-08 18:50:40.547 

(11 row(s) affected) 

当操作类型1为 “ClockIn” 和操作类型2是 “CLOCKOUT”。为了简洁,我还修剪了User,Project和Description列。

我需要生成,在纯SQL,一个结果集,如:

Description | Total Time 

对于每个ClockIn/CLOCKOUT对。

我想这实际上会很简单,我只是不太确定接近它的方式。

编辑:用户将能够同时计时到多个项目,虽然通过首先缩小结果集到单个项目,这应该不会对这里的逻辑有任何区别。

+0

你想要什么叫做临时连接操作。 – kasperjj 2008-11-09 03:25:43

+0

您能否详细说明或链接到一些信息? – FlySwat 2008-11-09 03:28:58

回答

1

我同意设计不是最大的 - 一个以单行为起点的基于事件的结构可能会为您节省很多时间。在这种情况下,当有人进入时,您可以创建一个空结束日期的记录。然后,在结束日期时填入结束日期。

但是,这不是你问的。这是解决问题的方法:

DECLARE @clock TABLE (ClockActionID INT PRIMARY KEY IDENTITY, ActionType INT, ActionDateTime DATETIME) 

INSERT INTO @clock (ActionType, ActionDateTime) VALUES (1,'20080101 00:00:00') 
INSERT INTO @clock (ActionType, ActionDateTime) VALUES (2,'20080101 00:01:00') 
INSERT INTO @clock (ActionType, ActionDateTime) VALUES (1,'20080101 00:02:00') 
INSERT INTO @clock (ActionType, ActionDateTime) VALUES (2,'20080101 00:03:00') 
INSERT INTO @clock (ActionType, ActionDateTime) VALUES (1,'20080101 00:04:00') 
INSERT INTO @clock (ActionType, ActionDateTime) VALUES (2,'20080101 00:05:00') 
INSERT INTO @clock (ActionType, ActionDateTime) VALUES (1,'20080101 00:06:00') 
INSERT INTO @clock (ActionType, ActionDateTime) VALUES (2,'20080101 00:07:00') 
INSERT INTO @clock (ActionType, ActionDateTime) VALUES (1,'20080101 00:08:12') 
INSERT INTO @clock (ActionType, ActionDateTime) VALUES (2,'20080101 00:09:00') 

-- Get the range 
SELECT ActionDateTime CheckIn, 
    (SELECT TOP 1 ActionDateTime 
    FROM @clock C2 
    WHERE C2.ActionDateTime > C.ActionDateTime) CheckOut 
FROM @clock C 
WHERE ActionType = 1 

-- Get the duration 
SELECT DATEDIFF(second, ActionDateTime, 
    (SELECT TOP 1 ActionDateTime 
    FROM @clock C2 
    WHERE C2.ActionDateTime > C.ActionDateTime) 
)/60.0 Duration_Minutes 
FROM @clock C 
WHERE ActionType = 1 

请注意,我使用一个表变量与MS SQL Server的工作只是为了测试。根据需要更改。还请注意,SQL Server 2000 在执行此类查询时性能不佳。以下是测试结果:

CheckIn     CheckOut 
2008-01-01 00:00:00.000 2008-01-01 00:01:00.000 
2008-01-01 00:02:00.000 2008-01-01 00:03:00.000 
2008-01-01 00:04:00.000 2008-01-01 00:05:00.000 
2008-01-01 00:06:00.000 2008-01-01 00:07:00.000 
2008-01-01 00:08:12.000 2008-01-01 00:09:00.000 

Duration_Minutes 
1.000000 
1.000000 
1.000000 
1.000000 
0.800000 
1

我认为您的原始存储架构存在缺陷。你从时钟的角度来看它,因此ClockAction。为什么不从项目的角度来看?

表ProjectAction(专案编号,用户标识,类型,开始,结束)

那么简单GROUP BY应该做的伎俩。

0

你有没有想过这样的事情:

  • 有人忘记打卡下班,因此他们似乎主频两次?
  • 有人忘记进来,因此看起来他们看起来两次?

在第一种情况下,简单地忽略第二次输入是否正确?接受的答案将两个时钟输入绑定到相同的时钟输出。那是对的吗?

在第二种情况下,第二次输出将被忽略。那是对的吗?