Pergunta

Eu estou escrevendo um programa de controle de tempo simples de gerenciar meus próprios projetos. Eu sou um grande fã de manter o código de relatórios no banco de dados, então eu tenho de tentar criar algumas sprocs que geram as faturas e planilhas etc.

Eu tenho uma tabela que contém Ações Despertador, IE "Punch In", e "Punch Out". Ele também contém o usuário que fez essa ação, o projeto associado com a ação, e a data / hora atual.

I pode selecionar a partir desta tabela para obter relógio de por um tempo específico / projecto / e usuário, mas eu quero agregar-lo para baixo para que cada clock dentro e fora é convertido a partir de 2 linhas para uma única linha que contém o tempo total.

Por exemplo, aqui está um exemplo de saída:

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)

Onde ActionType 1 é "ClockIn" e ActionType 2 é "ClockOut". Eu também podadas fora do Usuário, Projeto, e Inscrição colunas para a brevidade.

Eu preciso gerar, no SQL puro, um conjunto de resultados como:

Description   |    Total Time

Para cada ClockOut Par ClockIn /.

Eu acho que isso vai realmente ser bastante simples, eu apenas não estou completamente certo de que maneira de abordá-lo.

EDIT:. O usuário será capaz de relógio em vários projetos simultaneamente, embora de primeira estreitamento do conjunto de resultados para um único projeto, isso não deve fazer qualquer diferença para a lógica aqui

Foi útil?

Solução

Eu concordo que o projeto não é o maior - uma estrutura baseada em eventos com uma única linha para a partida final, provavelmente poupar muito tempo. Nesse caso, você pode criar um registro com uma data final nulo quando alguém relógios. Em seguida, preencha a data final quando eles relógio fora.

Mas, isso não é o que você pediu. Esta é a solução para o seu problema:

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

Note que eu estou usando uma variável de tabela que trabalha com MS SQL Server apenas para teste. Alterar conforme necessário. Também nota que o SQL Server 2000 não um bom desempenho com consultas como este. Aqui estão os resultados do teste:

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

Outras dicas

Eu acho que o esquema de armazenamento original é falho. Você está olhando para ele a partir da perspectiva do relógio, daí ClockAction. Por que não na perspectiva do projeto?

TABLE ProjectAction (projectId, Userid, Type, Start, End)

Em seguida, um simples GROUP BY deve fazer o truque.

Você já pensou em coisas como:

  • alguém se esquece de relógio para fora, e, portanto, parece que eles cronometrado em duas vezes?
  • alguém se esquece de relógio, e, assim, parece que eles cronometrado para fora duas vezes?

No primeiro caso, é correto simplesmente ignorar o segundo relógio-in? A resposta aceita ligará ambos relógio-ins para o mesmo clock-out. Isso está correto?

No segundo caso, o segundo relógio-out será ignorado. Isso está correto?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top