Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
839 connectés 

  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  Durée de plages de présence

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Durée de plages de présence

n°2260804
Tibar
Posté le 20-06-2015 à 07:54:11  profilanswer
 

Bonjour,
 
J'ai un petit problème sur une requête, je ne m'en sors pas. Je dois calculer des durées de présence.
Ma table se présente sous cette forme :  
 
ID_CLIENT; MOIS; XXXX
 
Dans cette table, j'ai par exemple :  
 
1; 201401
1; 201402
1; 201403
1; 201411
1; 201412
1; 201501
1; 201506
2; 201010
2; 201011
2; 201108
2; 201109
2; 201110
2; 201306
 
Mon objectif serait de sortir ça :  
ID_CLIENT; MOIS_DEBUT; MOIS_FIN; DUREE
1; 201401; 201403; 3
1; 201411; 201501; 3
1; 201506; 201506; 1
2; 201010; 201011; 2
2; 201108; 201110; 3
2; 201306; 201306; 1
 
Pour le moment, j'ai une requête qui me sort, pour chaque ID_CLIENT, la valeur de MOIS_DEBUT, je fais :  
SELECT  
P.MOIS
, P1.MOIS
FROM PRESENCE P
LEFT OUTER JOIN PRESENCE P1 ON P1.ID_CLIENT = P.ID_CLIENT AND P1.MOIS = P.MOIS - 1
WHERE P1.MOIS IS NULL
ORDER BY P.ID_CLIENT, P.MOIS
 
ce qui me sort tous les MOIS pour lesquels le mois précédent ne fait pas partie d'une plage de présence du client, soit
1; 201401; null
1; 201411; null
1; 201506; null
2; 201010; null
2; 201108; null
2; 201306; null
 
J'ai donc essayé de faire ça :  
 
SELECT  
P.ID_CLIENT
P.MOIS
, P1.MOIS
P.MOIS
, P2.MOIS
FROM PRESENCE P
LEFT OUTER JOIN PRESENCE P1 ON P1.ID_CLIENT = P.ID_CLIENT AND P1.MOIS = P.MOIS - 1
LEFT OUTER JOIN PRESENCE P2 ON P2.ID_CLIENT = P.ID_CLIENT AND P2.MOIS = P.MOIS + 1
WHERE (P1.MOIS IS NULL OR P2.MOIS IS NULL)
AND P.ID_CLIENT = 1
ORDER BY P.ID_CLIENT, P.MOIS
 
ce qui me sort, pour le client 1  
1; 201401; null; 201401; 201402
1; 201403; 201402; 201403; null
1; 201411; null; 201411; 201412
1; 201501; 201412;201501; null
 
(je fais ça de tête, je n'ai pas l'outil de requêtage sous la main)
 
Le résultat attendu n'est pas loin, mais impossible pour moi de mettre sur la même ligne la date de début et la date de fin, et donc de calculer la durée.
 
Merci,
 
 
 

mood
Publicité
Posté le 20-06-2015 à 07:54:11  profilanswer
 

n°2260828
lasnoufle
La seule et unique!
Posté le 21-06-2015 à 07:28:06  profilanswer
 

Quel SGBD?

 

Si Oracle, il faut que tu regardes du cote de CONNECT BY.
Autre SGBD, j'en sais rien.
Et aussi fait gaffe a ton mois - dans ton exemple, je pense pas que ca passe comme il faut d'une annee a l'autre (ca depend du type bien sur)


Message édité par lasnoufle le 21-06-2015 à 07:30:28

---------------
C'était vraiment très intéressant.
n°2260857
Oliiii
Posté le 22-06-2015 à 10:01:56  profilanswer
 

Ça c'est déjà un bon début (pour SQL Server), c'est améliorable niveau perf si nécessaire (si tu as beaucoup de lignes il te faudra au minimum un index sur ID_CLIENT, MOIS):

Code :
  1. ;WITH cte AS (
  2.     SELECT a.ID_CLIENT, a.MOIS, ROW_NUMBER() OVER (PARTITION BY a.ID_CLIENT, CASE WHEN c.MOIS IS NULL THEN 0 ELSE 1 END ORDER BY a.ID_CLIENT, a.MOIS) n
  3.     FROM @Presence a
  4.         LEFT JOIN @Presence b ON b.ID_CLIENT = a.ID_CLIENT AND b.MOIS = DATEADD(MONTH, 1, a.MOIS)
  5.         LEFT JOIN @Presence c ON c.ID_CLIENT = a.ID_CLIENT AND c.MOIS = DATEADD(MONTH, -1, a.MOIS)
  6.     WHERE b.ID_CLIENT IS NULL
  7.         OR c.ID_CLIENT IS NULL
  8.     )
  9. SELECT a.ID_CLIENT, MIN(a.MOIS) MOIS_DEBUT, MAX(a.MOIS) MOIS_FIN, DATEDIFF(MONTH, MIN(a.MOIS), MAX(a.MOIS)) + 1 DUREE
  10. FROM cte a
  11. GROUP BY a.ID_CLIENT, a.n
  12. ORDER BY a.ID_CLIENT, MIN(a.MOIS)

n°2261025
Tibar
Posté le 24-06-2015 à 04:45:43  profilanswer
 

Salut,

 

Merci pour les réponses, je suis sous Oracle, j'ai contourné un peu en créant deux tables temporaires, je vais creuser le connect by.

 

Pour les CTE, c'est en gros un principe de table temporaire ?

 

Sinon en terme de performance, les index sont là et sur 10 M de lignes ça tourne plutôt bien en le faisant en deux étapes...

 

Est-ce que c'est du ressort du SGBD de faire ces traitements ? Est-ce qu'il y aurait un modèle (sans utiliser les triggers) pour simplifier tout ça ?

n°2261037
Oliiii
Posté le 24-06-2015 à 08:44:29  profilanswer
 

La CTE c'est en général un moyen d’écrire la query d'une façon plus claire, ça peut pratiquement toujours être réécris de manière standard.
 
Dans ça cas ci je dirais que c'est du ressort du SGBD de faire le traitement vu que ce n'est pas un traitement ligne par ligne, c'est pas du calcul pur et dur et au final ça joue vraiment avec les données.


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  Durée de plages de présence

 

Sujets relatifs
Decompter un chiffre sur un durée[RESOLU] Plages horaires successives
presence raccourci bureau et le supprimer vbs scriptTest présence JS
vérification présence valeur dans tableau associatif[VBS] Detecter la présence d'une clé USB
Tester la présence d'un raccourci sur le bureauCalcul de durée entre deux dates.
[Access] Formulaire plusieurs enreg : signaler présence d'infosCalculer la durée d'un pas selon le tempo et la signature rythmique
Plus de sujets relatifs à : Durée de plages de présence


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR