0

我正在编写一个简单的时间跟踪程序来管理我自己的项目。我非常喜欢在数据库中保存报告代码,所以我一直在尝试创建一些 sprocs 来生成发票和时间表等。

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

我可以从此表中选择以获取特定时间/项目/和用户的打卡信息,但我想将其汇总,以便每个打卡和打卡都从 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)

其中 ActionType 1 是“ClockIn”,ActionType 2 是“ClockOut”。为简洁起见,我还删除了 User、Project 和 Description 列。

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

Description   |    Total Time

对于每个 ClockIn / ClockOut 对。

我认为这实际上会相当简单,我只是不太确定采用哪种方法。

编辑:用户将能够同时进入多个项目,尽管首先将结果集缩小到单个项目,这对这里的逻辑没有任何影响。

4

3 回答 3

1

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

表 ProjectAction(Projectid、用户 ID、类型、开始、结束)

然后一个简单的 GROUP BY 应该可以解决问题。

于 2008-11-09T03:41:52.363 回答
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
于 2008-11-09T04:47:18.240 回答
0

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

  • 有人忘记打卡,因此看起来他们打卡了两次?
  • 有人忘记打卡,因此看起来他们打卡了两次?

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

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

于 2008-11-09T11:06:39.457 回答