我正在写一个简单的时间跟踪程序,以管理自己的项目。我是个大风扇保持报告中的代码数据库所以我一直试图建立一些sprocs产生的发票和时间表等等。

我有一个表,其中包含钟的行动,即"冲"和"穿出"。它还包含用户,没有这一行动,该项目相关的行动,而目前的日期/时间。

我可以选择从该表中得到时钟在一个特定的时间/项目/和用户,但是我想要的聚集它下来,这样,每个时钟转换从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)

在ActionType1是"ClockIn"和ActionType2是"ClockOut".我也修剪了用户、项目,并说明列于简洁。

我需要生成,纯SQL,结果设定的,如:

Description   |    Total Time

每个ClockIn/ClockOut对。

我想,这实际上将相当简单,我只是不确定哪种方式方法。

编辑:用户将能够钟到多个项目同时,虽然通过第一个缩小的结果集中于单个项目,这不应该使任何区别在逻辑在这里。

有帮助吗?

解决方案

我同意这个设计并不是最好的 - 基于事件的结构只有一行的开端可能会为你节省很多时间。在这种情况下,当有人进入时,您可以创建一个带有空结束日期的记录。然后,在他们退出时填写结束日期。

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

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

其他提示

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

TABLE ProjectAction(Projectid,Userid,Type,Start,End)

然后一个简单的GROUP BY就可以了。

你有没有想过的东西,如:

  • 有人忘记了时钟,并由此看来他们输入的两倍?
  • 有人忘记了时钟,并由此看来他们输了两次?

在第一种情况下,这是正确的,忽略的第二钟?所接受的答案将结合这两个钟载于同一个时钟。是正确的?

在第二种情况下,在第二时钟将被忽略。是正确的?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top