2008-11-09 65 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

你有沒有想過這樣的事情:

  • 有人忘記打卡下班,因此他們似乎主頻兩次?
  • 有人忘記進來,因此看起來他們看起來兩次?

在第一種情況下,簡單地忽略第二次輸入是否正確?接受的答案將兩個時鐘輸入綁定到相同的時鐘輸出。那是對的嗎?

在第二種情況下,第二次輸出將被忽略。那是對的嗎?