2008-11-09 11 views
0

Я пишу простую программу отслеживания времени для управления собственными проектами. Я большой поклонник хранения кода отчетности в базе данных, поэтому я пытался создать несколько sprocs, которые генерируют счета-фактуры и расписания и т. Д.Как бы вычислить временные рамки из списка регистрации и проверки?

У меня есть таблица, содержащая Clock Actions, 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 пары.

Я полагаю, что это на самом деле будет довольно просто, я просто не совсем уверен, к какому пути это подходит.

EDIT: Пользователь может одновременно выполнять одновременное выполнение нескольких проектов, хотя сначала сужая результирующий набор до одного проекта, это не должно иметь никакого значения для логики здесь.

+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 (ProjectID, Userid, тип, Start, End)

Тогда простой GROUP BY следует сделать трюк.

0

Вы думали о таких вещах, как:

  • кто-то забывает часы из, и, таким образом, оказывается, что они с тактовой частотой в два раза?
  • Кто-то забывает часы, и, следовательно, кажется, что они вышли дважды?

В первом случае, правильно ли просто игнорировать второй такт? Принятый ответ свяжет оба таймера с одним и тем же таймаутом. Это верно?

Во втором случае второй тайм-аут будет проигнорирован. Это верно?