IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage SQL Discussion :

Requête SQL de dédoublonage


Sujet :

Langage SQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Mars 2009
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 20
    Par défaut Requête SQL de dédoublonage
    Salut à tous,

    J'aurais besoin de votre assistance, s'il vous plaît. Je suis en train de travailler sur une requête de sélection à partir d'une table de pointage des collaborateurs (je travail dans un environnement MS ACCESS 2016), mais le problème est que cette table contient des doublons avec de légères variations dans les horaires.

    Un exemple pourrait rendre les choses plus claires.

    Table sources contient les données suivants :

    EMPLOYEE_ID LoginTime LogoutTime
    8858043 2024-01-06 07:58:48.000 2024-01-06 14:03:05.000
    8858043 2024-01-06 07:59:47.000 2024-01-06 14:05:05.000
    8858043 2024-01-06 15:00:06.000 2024-01-06 18:05:40.000
    8858043 2024-01-06 15:00:29.000 2024-01-06 18:01:40.000

    Résultats souhaités :

    EMPLOYEE_ID LoginTime LogoutTime
    8858043 2024-01-06 07:58:48.000 2024-01-06 14:05:05.000
    8858043 2024-01-06 15:00:06.000 2024-01-06 18:05:40.000


    à l'aide de ChatGPT j'ai obtenu cette requête qui fonctionne presque sauf que ça me donne pour chaque groupe de login/logout la 2ème connexions ey n'ont pas la première.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
     
    SELECT 
        CD1.EMPLOYEE_ID, 
        MIN(CD1.LoginTime) AS FirstLogin, 
        MAX(CD2.LogoutTime) AS LastLogout
    FROM 
        Telephonie AS CD1 
    LEFT JOIN 
        Telephonie AS CD2 
    ON 
        (CD1.LoginTime < CD2.LogoutTime) AND (CD1.EMPLOYEE_ID = CD2.EMPLOYEE_ID)
    WHERE 
        NOT EXISTS (
            SELECT 1
            FROM Telephonie AS CD3
            WHERE CD3.EMPLOYEE_ID = CD1.EMPLOYEE_ID
              AND CD3.LoginTime > CD1.LoginTime
              AND CD3.LoginTime < CD2.LogoutTime
        )
    GROUP BY 
        CD1.EMPLOYEE_ID,CD1.LoginTime

    Pouvez-vous m'aider pls ?

    merci d'avance.

  2. #2
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 636
    Billets dans le blog
    10
    Par défaut
    La difficulté ici est de définir pourquoi vous sélectionnez la borne de début de la première ligne avec la borne de fin de la deuxième, plutôt que la borne de fin de la troisième ou de la quatrième...
    On comprend intuitivement que quand l'écart est de l'ordre de quelques secondes, on prend la ligne la plus forte, mais en SQL, il faut le traduire par une règle. Quelle est-elle ?

  3. #3
    Membre averti
    Inscrit en
    Mars 2009
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 20
    Par défaut
    Citation Envoyé par escartefigue Voir le message
    La difficulté ici est de définir pourquoi vous sélectionnez la borne de début de la première ligne avec la borne de fin de la deuxième, plutôt que la borne de fin de la troisième ou de la quatrième...
    On comprend intuitivement que quand l'écart est de l'ordre de quelques secondes, on prend la ligne la plus forte, mais en SQL, il faut le traduire par une règle. Quelle est-elle ?
    L'objectif est de créer une timeline de connexion/déconnexion, d'une façon plus concrète conserver que la première login et la dernière logout de chaque intervalle de connexion/déconnexion

    un autre exemple pour simplifier le besoin :

    1er tableau = data source
    2ème tableau = le résultat souhaité

    Nom : Sans titre.png
Affichages : 305
Taille : 6,0 Ko

    j'espère que c'est clair maintenant

  4. #4
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 636
    Billets dans le blog
    10
    Par défaut
    C'est clair depuis le départ, mais il faut une règle traduisible en SQL
    Là, dans l'exemple, les lignes en jaune sont en doublon ok, mais la couleur jaune ce n'est pas une règle traduisible en SQL
    Par exemple, la règle peut être : il considérer qu'il y a doublon quand l'écart est de moins d'une heure, moins de 10 minutes...

  5. #5
    Membre averti
    Inscrit en
    Mars 2009
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 20
    Par défaut
    Je m'excuse, mais je n'ai pas saisi pleinement ta question. Pour moi, la règle consiste à conserver le (min LoginTime) et le (max LogoutTime) de chaque intervalle chevauché.

    Le script que j'ai initialement intégré fonctionne partiellement. Il conserve les intervalles souhaités, mais inclut la dernière connexion plutôt que la première.

    Désolé, je suis encore novice dans le langage SQL.

  6. #6
    Modérateur
    Avatar de escartefigue
    Homme Profil pro
    bourreau
    Inscrit en
    Mars 2010
    Messages
    10 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : bourreau
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2010
    Messages : 10 636
    Billets dans le blog
    10
    Par défaut
    C'est ce que j'ai mis en rouge ci-dessous qui manquait comme information

    Citation Envoyé par Sniper69 Voir le message
    Je m'excuse, mais je n'ai pas saisi pleinement ta question. Pour moi, la règle consiste à conserver le (min LoginTime) et le (max LogoutTime) de chaque intervalle chevauché.
    La méthode classique pour satisfaire ce genre de besoins est d'utiliser la méthode dite "Tabibitosan", c'est l'objet de la réponse de Waldar qui précède, il faut pour cela que votre SGBD accepte les fonctions fenêtrés (c'est à dire que ce ne soit pas Access, ou MySQL dans une version antérieure à la V8).

  7. #7
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Si votre database n'a pas de fonctions natives pour gérer ceci, la requête SQL peut être complexe et pas très performantes à l'exécution.
    Essayez ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    with cte_data (Employee_Id, LoginTime, LogoutTime) as
    (
    select 8858043, timestamp '2024-01-06 07:58:48', timestamp '2024-01-06 14:03:05' union all
    select 8858043, timestamp '2024-01-06 07:59:47', timestamp '2024-01-06 14:05:05' union all
    select 8858043, timestamp '2024-01-06 15:00:06', timestamp '2024-01-06 18:05:40' union all
    select 8858043, timestamp '2024-01-06 15:00:29', timestamp '2024-01-06 18:01:40'
    )
      ,  cte_LogoutMax (Employee_Id, LoginTime, LogoutTime, LogoutTime_max) as
    (
    select Employee_Id, LoginTime, LogoutTime
         , max(LogoutTime) over(partition by Employee_Id order by LoginTime, LogoutTime rows unbounded preceding) as LogoutTime_max
      from cte_data
    )
      ,  cte_GrpStart (Employee_Id, LoginTime, LogoutTime, GrpStart) as
    (
    select Employee_Id, LoginTime, LogoutTime
         , case when LoginTime <= lag(LogoutTime_max) over(partition by Employee_Id order by LoginTime, LogoutTime) then 0 else 1 end
      from cte_LogoutMax
    )
      ,  cte_GrpId (Employee_Id, LoginTime, LogoutTime, GrpId) as
    (
    select Employee_Id, LoginTime, LogoutTime
         , sum(GrpStart) over(partition by Employee_Id order by LoginTime rows unbounded preceding)
      from cte_GrpStart
    )
      select Employee_Id
           , min(LoginTime)  as LoginTime
           , max(LogoutTime) as LogoutTime
        from cte_GrpId
    group by Employee_Id, GrpId
    order by Employee_Id, GrpId;
     
    Employee_Id  LoginTime            LogoutTime         
    -----------  -------------------  -------------------
        8858043  2024-01-06 07:58:48  2024-01-06 14:05:05
        8858043  2024-01-06 15:00:06  2024-01-06 18:05:40
    Edit: j'ai corrigé une typo dans le code.

  8. #8
    Membre Expert
    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Décembre 2019
    Messages
    1 176
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Décembre 2019
    Messages : 1 176
    Par défaut
    Bonjour,

    Dans Oracle avec le Pattern Matching:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    select * from Telephonie 
    match_recognize(partition by employee_id
                    order by logintime
                    measures min(logintime) as logintime,
                             greatest(max(a.logouttime), next(a.logouttime)) as logouttime
                    pattern (a+)
                    define A as a.logouttime > next(a.logintime)
                   );

Discussions similaires

  1. Datagridview & requte sql
    Par oami89 dans le forum VB.NET
    Réponses: 8
    Dernier message: 14/04/2011, 08h40
  2. Réponses: 5
    Dernier message: 06/10/2009, 09h37
  3. Réponses: 4
    Dernier message: 11/06/2009, 16h03
  4. comment parametrer une requte sql ds ireport
    Par hamzuss dans le forum Jasper
    Réponses: 3
    Dernier message: 17/03/2009, 20h01
  5. Requte Sql Avancée, question ... ? Estce possible ?
    Par plex dans le forum Administration
    Réponses: 8
    Dernier message: 14/12/2005, 15h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo