0

自分のプロジェクトを管理するための簡単な時間追跡プログラムを書いています。私はレポート コードをデータベースに保存するのが大好きなので、請求書やタイムシートなどを生成するいくつかの sproc を作成しようとしています。

クロック アクション、つまり「パンチ イン」と「パンチ アウト」を含むテーブルがあります。また、このアクションを実行したユーザー、アクションに関連付けられたプロジェクト、および現在の日付/時刻も含まれています。

このテーブルから選択して、特定の時間/プロジェクト/およびユーザーの出勤を取得できますが、各出勤が 2 行から合計時間を含む 1 行に変換されるように集計したいと考えています。

たとえば、出力例を次に示します。

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」です。また、簡潔にするために、ユーザー、プロジェクト、および説明の列を削除しました。

純粋な SQL で、次のような結果セットを生成する必要があります。

Description   |    Total Time

各クロックイン/クロックアウト ペア。

これは実際にはかなり単純だと思いますが、どの方法でアプローチすればよいかわかりません。

編集: ユーザーは複数のプロジェクトに同時にクロックインできますが、最初に結果セットを 1 つのプロジェクトに絞り込むことで、ここでのロジックに違いはありません。

4

3 に答える 3

1

元のストレージ スキーマに欠陥があると思います。時計の視点から見ているので、ClockAction です。なぜプロジェクトの観点からではないのですか?

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

次に、単純な GROUP BY でうまくいくはずです。

于 2008-11-09T03:41:52.363 に答える
1

設計が最適ではないことに同意します。開始と終了を 1 行で行うイベント ベースの構造により、おそらく多くの時間を節約できます。その場合、誰かが出勤したときに終了日が null のレコードを作成できます。次に、退勤したときに終了日を入力します。

しかし、それはあなたが尋ねたものではありません。これはあなたの問題の解決策です:

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

次のようなことを考えたことがありますか。

  • 誰かが退出を忘れて、2 回出勤したように見えますか?
  • 誰かが出勤するのを忘れて、2 回出勤したように見えますか?

最初のケースでは、単純に 2 回目の出勤を無視するのは正しいですか? 受け入れられた回答は、両方のクロックインを同じクロックアウトにバインドします。あれは正しいですか?

2 番目のケースでは、2 回目の退勤は無視されます。あれは正しいですか?

于 2008-11-09T11:06:39.457 に答える