Domanda

Sto scrivendo un semplice programma di monitoraggio del tempo per gestire i miei progetti. Sono un grande fan della conservazione del codice di segnalazione nel database, quindi ho cercato di creare alcuni sprocs che generano fatture, schede attività ecc.

Ho una tabella che contiene Clock Actions, IE "Punch In", e "Punch Out". Contiene inoltre l'utente che ha eseguito questa azione, il progetto associato all'azione e la data / ora correnti.

Posso selezionare da questa tabella per ottenere il clock in di un tempo / progetto / utente specifico, ma voglio aggregarlo in modo che ogni clock in e out sia convertito da 2 righe in una singola riga contenente il tempo totale.

Ad esempio, ecco un output di esempio:

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)

Dove ActionType 1 è " ClockIn " e ActionType 2 è "ClockOut". Ho anche eliminato le colonne Utente, Progetto e Descrizione per brevità.

Devo generare, in puro SQL, un set di risultati come:

Description   |    Total Time

Per ogni coppia ClockIn / ClockOut.

Immagino che questo sarà in realtà abbastanza semplice, non sono proprio sicuro del modo in cui affrontarlo.

EDIT: l'utente sarà in grado di sincronizzare più progetti contemporaneamente, sebbene restringendo prima il set di risultati a un singolo progetto, ciò non dovrebbe fare alcuna differenza alla logica qui.

È stato utile?

Soluzione

Concordo sul fatto che il design non è il massimo: una struttura basata su eventi con una sola riga per l'inizio-fine probabilmente ti farà risparmiare molto tempo. In tal caso, è possibile creare un record con una data di fine nulla quando qualcuno accede. Quindi, inserire la data di fine quando si disconnettono.

Ma non è quello che hai chiesto. Questa è la soluzione al tuo 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

Nota che sto usando una variabile di tabella che funziona con MS SQL Server solo per i test. Cambia se necessario. Si noti inoltre che SQL Server 2000 non funziona bene con query come questa. Ecco i risultati del test:

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

Altri suggerimenti

Penso che il tuo schema di archiviazione originale sia difettoso. Lo stai guardando dal punto di vista dell'orologio, quindi ClockAction. Perché non dal punto di vista del progetto?

TABELLA ProjectAction (Projectid, Userid, Type, Start, End)

Quindi un semplice GROUP BY dovrebbe fare il trucco.

Hai pensato a cose come:

  • qualcuno dimentica di disconnettersi, e quindi sembra che abbiano registrato due volte?
  • qualcuno ha dimenticato di fare il login, e quindi sembra che si siano disconnessi due volte?

Nel primo caso, è corretto ignorare semplicemente il secondo clock-in? La risposta accettata assocerà entrambi gli ingressi allo stesso clock. È corretto?

Nel secondo caso, il secondo timeout verrà ignorato. È corretto?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top