我将如何计算时间跨度从一个名单的检查和检查出局?
-
07-07-2019 - |
题
我正在写一个简单的时间跟踪程序,以管理自己的项目。我是个大风扇保持报告中的代码数据库所以我一直试图建立一些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就可以了。
你有没有想过的东西,如:
- 有人忘记了时钟,并由此看来他们输入的两倍?
- 有人忘记了时钟,并由此看来他们输了两次?
在第一种情况下,这是正确的,忽略的第二钟?所接受的答案将结合这两个钟载于同一个时钟。是正确的?
在第二种情况下,在第二时钟将被忽略。是正确的?