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 de recherche de doublons à améliorer


Sujet :

Langage SQL

  1. #1
    Membre éclairé Avatar de Nerva
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 366
    Par défaut Requête de recherche de doublons à améliorer
    Bonjour.

    Je suis en train de corriger une table qui contient environ 10000 lignes. Il y a eu pas mal d'erreurs de saisie, ce qui fait qu'elle comporte un nombre important de doublons que je dois supprimer (la table n'avait pas de contrainte d'unicité).

    VAC_ID (clé primaire auto-incrémentée)
    VAC_DATE
    D1_ID
    D2_ID

    Il ne doit y avoir qu'un seul "couple" D1_ID et D2_ID par VAC_DATE. J'ai donc créé cette requête pour trouver les doublons :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT COUNT(*) AS VAC_DOUBLON, D1_ID, D2_ID, VAC_DATE
    FROM T_VACATIONS
    GROUP BY D1_ID, D2_ID, VAC_DATE
    HAVING COUNT(*) > 1
    ORDER BY VAC_DATE ASC, D1_ID ASC
    Elle fait le boulot mais comme il y a beaucoup de lignes à supprimer, j'aimerais savoir comment faire pour afficher également la colonne VAC_ID afin que je puisse créer un script pour supprimer en un clic tous les doublons (et même certains "triblons" et "quadrublons").

    Merci.

  2. #2
    Expert confirmé
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 310
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 310
    Billets dans le blog
    17
    Par défaut
    Tu peux faire comme ça :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    SELECT ALL VAC_ID, D1_ID, D2_ID, VAC_DATE
    FROM T_VACATIONS
    WHERE (D1_ID, D2_ID, VAC_DATE) IN (
        SELECT ALL D1_ID, D2_ID, VAC_DATE
        FROM T_VACATIONS
        GROUP BY 1, 2, 3
        HAVING COUNT(*) > 1
    )
    ORDER BY 2 ASC, 3 ASC, 4 ASC;

  3. #3
    Membre éclairé Avatar de Nerva
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 366
    Par défaut
    Non, erreur de syntaxe.

  4. #4
    Expert confirmé
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 310
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 310
    Billets dans le blog
    17
    Par défaut
    Qu'est-ce qui t'empêche de la communiquer ou de la corriger ?

    Je relis, je ne vois pas d'erreur de syntaxe. Quel est ton SGBD ?

  5. #5
    Membre éclairé Avatar de Nerva
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 366
    Par défaut
    Il s'agit d'HSQLDB dans LO Base. J'ai testé en remplaçant le GROUP BY 1, 2, 3 par le nom des colonnes mais rien n'y fait (table dupliquée en T_VACATIONS2 pour les tests) :

    Nom : Capture d’écran du 2023-01-22 14-39-08.png
Affichages : 188
Taille : 27,3 Ko

    Et en exécutant en SQL direct :

    Nom : Capture d’écran du 2023-01-22 14-39-49.png
Affichages : 235
Taille : 46,3 Ko

  6. #6
    Expert confirmé
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 310
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 310
    Billets dans le blog
    17
    Par défaut
    HSQLDB dans LO Base
    Inconnu au bataillon.

    Le seul truc un peu inhabituel est le (cols) IN (SELECT cols), sais-tu si la syntaxe est supportée ? Pour savoir tu peux essayer ces 2 requêtes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    SELECT (123, 234) IN ((123, 234)); -- 1/TRUE
    SELECT (123, 234) IN (SELECT ALL 123, 234); -- 1/TRUE
    Sinon tu peux reformuler la requête proposée précédemment en :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT ALL VAC_ID, D1_ID, D2_ID, VAC_DATE
    FROM T_VACATIONS AS t1
    INNER JOIN (
        SELECT ALL D1_ID, D2_ID, VAC_DATE
        FROM T_VACATIONS
        GROUP BY 1, 2, 3
        HAVING COUNT(*) > 1
    ) AS t2 ON TRUE
        AND t1.D1_ID = t2.D1_ID
        AND t1.D2_ID = t2.D2_ID
        AND t1.VAC_DATE = t2.VAC_DATE
    ;

  7. #7
    Membre éclairé Avatar de Nerva
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 366
    Par défaut
    Je ne sais pas si c'est supporté (je ne comprends d'ailleurs pas ce que signifie ces deux lignes, si ce n'est la numérotation des colonnes).

    Ta deuxième requête est fonctionnelle (en mode SQL direct) mais le résultat n'est pas bon : elle n'affiche que la dernière ligne de la table (qui n'est pas doublonnée).

  8. #8
    Expert confirmé
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 310
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 310
    Billets dans le blog
    17
    Par défaut
    Citation Envoyé par Nerva Voir le message
    Je ne sais pas si c'est supporté (je ne comprends d'ailleurs pas ce que signifie ces deux lignes, si ce n'est la numérotation des colonnes).
    Ce sont 2 requêtes qui testent le support de (...) IN (...)

    Ta deuxième requête est fonctionnelle (en mode SQL direct) mais le résultat n'est pas bon : elle n'affiche que la dernière ligne de la table (qui n'est pas doublonnée).
    Donne un jeu de test.

  9. #9
    Membre éclairé Avatar de Nerva
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 366
    Par défaut
    Voilà un jeu partiel de 1579 lignes (fichier texte zippé) :

    t_vacations.sql.zip

  10. #10
    Expert confirmé
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 310
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 310
    Billets dans le blog
    17
    Par défaut
    Plus haut j'ai oublié de préfixer le nom de colonnes sélectionnées, correction :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    SELECT ALL t1.VAC_ID, t1.D1_ID, t1.D2_ID, t1.VAC_DATE
    FROM T_VACATIONS AS t1
    INNER JOIN (
        SELECT ALL D1_ID, D2_ID, VAC_DATE
        FROM T_VACATIONS
        GROUP BY 1, 2, 3
        HAVING COUNT(*) > 1
    ) AS t2 ON TRUE
        AND t1.D1_ID = t2.D1_ID
        AND t1.D2_ID = t2.D2_ID
        AND t1.VAC_DATE = t2.VAC_DATE
    ;

    J'obtiens les 69 lignes suivantes :

    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    227	102073	101024	2022-02-01
    228	102073	101024	2022-02-01
    229	102017	101033	2022-02-01
    230	102018	101031	2022-02-01
    231	102093	101045	2022-02-01
    232	102104	101022	2022-02-01
    233	102017	101033	2022-02-01
    234	102018	101031	2022-02-01
    235	102093	101045	2022-02-01
    236	102104	101022	2022-02-01
    368	102003	101050	2022-04-01
    379	102021	101063	2022-04-01
    396	102046	101068	2022-04-01
    397	102047	101021	2022-04-01
    423	102078	101063	2022-04-01
    444	102103	101063	2022-04-01
    449	102111	101046	2022-04-01
    461	102124	101057	2022-04-01
    464	102128	101037	2022-04-01
    466	102130	101003	2022-04-01
    467	102131	101050	2022-04-01
    469	102133	101039	2022-04-01
    473	102139	101064	2022-04-01
    474	102141	101040	2022-04-01
    476	102143	101066	2022-04-01
    493	102169	101061	2022-04-01
    497	102021	101063	2022-04-01
    498	102046	101068	2022-04-01
    499	102047	101021	2022-04-01
    500	102078	101063	2022-04-01
    501	102103	101063	2022-04-01
    502	102124	101057	2022-04-01
    503	102128	101037	2022-04-01
    504	102130	101003	2022-04-01
    505	102131	101050	2022-04-01
    506	102133	101039	2022-04-01
    507	102139	101064	2022-04-01
    508	102143	101066	2022-04-01
    509	102162	101051	2022-04-01
    510	102169	101061	2022-04-01
    511	102021	101063	2022-04-01
    512	102047	101021	2022-04-01
    513	102078	101063	2022-04-01
    514	102103	101063	2022-04-01
    515	102124	101057	2022-04-01
    516	102128	101037	2022-04-01
    517	102130	101003	2022-04-01
    518	102131	101050	2022-04-01
    519	102133	101039	2022-04-01
    520	102139	101064	2022-04-01
    521	102141	101040	2022-04-01
    522	102143	101066	2022-04-01
    523	102162	101051	2022-04-01
    524	102169	101061	2022-04-01
    525	102021	101063	2022-04-01
    526	102047	101021	2022-04-01
    527	102111	101046	2022-04-01
    528	102124	101057	2022-04-01
    529	102131	101050	2022-04-01
    530	102133	101039	2022-04-01
    531	102143	101066	2022-04-01
    532	102162	101051	2022-04-01
    533	102169	101061	2022-04-01
    534	102162	101051	2022-04-01
    535	102003	101050	2022-04-01
    1332	102031	101040	2022-11-01
    1444	102031	101040	2022-11-01
    1486	102031	101040	2022-12-01
    1532	102031	101040	2022-12-01
    Même chose avec la requête proposée initialement.

  11. #11
    Membre éclairé Avatar de Nerva
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 366
    Par défaut
    Ça ne fonctionne pas dans mon système, je n'obtiens là aucun retour. Je ne saurais pas dire d'où ça vient (pas du surnommage en lui-même puisque c'est parfaitement pris en charge, ça doit être quelque chose de plus global qui n'est pas accepté dans ce SGBDR).

    Merci encore.

  12. #12
    Expert confirmé
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 310
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 310
    Billets dans le blog
    17
    Par défaut
    Je ne vois pas trop ce qui pourrait bloquer, la 2nde version est une requête ultra-basique.

    Ton SGBD accepte-t-il les CTE ? Les fonctions d'analyse comme "ROW_NUMBER() OVER (...)" ?

    Que donnaient les 2 requêtes test de https://www.developpez.net/forums/d2.../#post11914021 ?

  13. #13
    Membre éclairé Avatar de Nerva
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 366
    Par défaut
    La première requête de test sortait uniquement la dernière ligne.

    Pour ce qui est des CTE et des fonctions d'analyse, j'ai un peu cherché sur le net et apparemment c'est géré mais la syntaxe ne doit pas être standard. Enfin je ne suis sûr de rien et je n'ai pas creusé puisque je n'ai jamais utilisé ces fonctions. Et il faut tenir compte aussi qu'il y a des différences entre la version standard du SGBDR et celle intégrée dans LO Base (je n'ai jamais trouvé de document qui énonce clairement les différences).

    Il y a bien un guide utilisateur mais je ne sais pas dans quelle section chercher pour avoir des réponses précises concernant ces fonctions (le PDF est corrompu) :

    https://hsqldb.org/doc/guide

  14. #14
    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
    Citation Envoyé par Nerva Voir le message
    Il ne doit y avoir qu'un seul "couple" D1_ID et D2_ID par VAC_DATE.
    Attention à ce point, ce n'est pas ce que vous avez codé.
    Un seul couple (D1_ID, D2_ID) par VAC_DATE signifie que ceci doit être considéré comme un doublon :
    Code txt : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    D1_ID  D2_ID  VAC_DATE
    -----  -----  ----------
        1      2  2023-01-23
        1      3  2023-01-23
    Or, votre requête n'identifie pas ce cas.

    L'erreur pouvant venir de la phrase citée, je préfère simplement que vous vérifiez ce point.

  15. #15
    Membre éclairé Avatar de Nerva
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 366
    Par défaut
    Oui, il ne s'agit pas d'un couple mais d'un triplet. Un doublon = 2 fois (ou plus) D1_ID D2_ID VAC_DATE

Discussions similaires

  1. Requête de recherche de doublon
    Par BernardBouree dans le forum Requêtes et SQL.
    Réponses: 9
    Dernier message: 30/03/2020, 19h36
  2. [MySQL] Requête pour recherche de doublons qui ne fonctionne plus : HTTP404
    Par HAbroc dans le forum PHP & Base de données
    Réponses: 6
    Dernier message: 24/06/2012, 11h13
  3. Requête pour rechercher des doublons partiels
    Par jubourbon dans le forum Langage SQL
    Réponses: 2
    Dernier message: 23/06/2011, 11h22
  4. Requête à le recherche de doublons
    Par titinesaku dans le forum Requêtes
    Réponses: 6
    Dernier message: 06/05/2011, 09h29
  5. [Requête/SQL]Recherche de doublons
    Par Mr T 94 dans le forum Requêtes et SQL.
    Réponses: 14
    Dernier message: 16/04/2007, 00h51

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