Question

J'écris un programme simple de suivi du temps pour gérer mes propres projets. Je suis un grand partisan de la conservation du code de rapport dans la base de données. J'ai donc essayé de créer quelques sprocs générant les factures et les feuilles de temps, etc.

J'ai une table qui contient les actions d'horloge, IE "Punch In" et "Punch Out". Il contient également l’utilisateur qui a effectué cette action, le projet associé à l’action et la date / heure en cours.

Je peux sélectionner dans ce tableau les horloges entrant pour une heure / projet / et un utilisateur spécifiques, mais je souhaite l'agréger de manière à ce que chaque horloge entrée et sortie soit convertie de 2 lignes en une seule ligne contenant le temps total.

Par exemple, voici un exemple de sortie:

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)

Où ActionType 1 est " ClockIn " et ActionType 2 est "ClockOut". J'ai également supprimé les colonnes Utilisateur, Projet et Description par souci de concision.

Je dois générer, en SQL pur, un ensemble de résultats tel que:

Description   |    Total Time

Pour chaque paire ClockIn / ClockOut.

Je pense que ce sera en fait assez simple, je ne sais pas trop comment l’approcher.

EDIT: l’utilisateur pourra effectuer simultanément des chronométrages dans plusieurs projets. Toutefois, si vous limitez tout d’abord le résultat à un seul projet, cela ne fera aucune différence dans la logique.

Était-ce utile?

La solution

Je conviens que la conception n'est pas ce qu'il y a de mieux - une structure basée sur des événements avec une seule ligne pour début-fin vous permettra probablement de gagner beaucoup de temps. Dans ce cas, vous pouvez créer un enregistrement avec une date de fin nulle lorsque quelqu'un se synchronise. Ensuite, renseignez la date de fin du processus.

Mais ce n’est pas ce que vous avez demandé. Voici la solution à votre problème:

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

Notez que j'utilise une variable de table qui fonctionne avec MS SQL Server uniquement pour les tests. Changer au besoin. Notez également que SQL Server 2000 ne fonctionne pas correctement avec des requêtes comme celle-ci. Voici les résultats du 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

Autres conseils

Je pense que votre schéma de stockage d'origine est défectueux. Vous le regardez du point de vue de l'horloge, d'où ClockAction. Pourquoi pas du point de vue du projet?

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

Ensuite, un simple GROUP BY devrait faire l'affaire.

Avez-vous pensé à des choses comme:

  • quelqu'un oublie de sortir, et il semble donc qu'ils ont enregistré deux fois?
  • quelqu'un oublie de faire son point, et il apparaît donc qu'il a frappé deux fois?

Dans le premier cas, est-il correct de simplement ignorer la deuxième heure d'arrivée? La réponse acceptée liera les deux entrées à la même sortie. Est-ce correct?

Dans le deuxième cas, la deuxième horloge sera ignorée. Est-ce correct?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top