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

SQL Oracle Discussion :

Regrouper le même champ de plusieurs lignes dans un nouveau champs - instruction connect by


Sujet :

SQL Oracle

  1. #1
    Membre du Club
    Inscrit en
    Juin 2008
    Messages
    102
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 102
    Points : 47
    Points
    47
    Par défaut Regrouper le même champ de plusieurs lignes dans un nouveau champs - instruction connect by
    Bonjour,

    J'ai une base de données qui contient une table d'historisation des contacts où il y a plusieurs lignes d'historisation de contacts pour un même identifiant de contrat.
    Je souhaiterais dans une vue récupérer les données de plusieurs lignes de contact communes avec le même identifiant de contrat:

    Nom : Capture.PNG
Affichages : 137
Taille : 29,2 Ko

    CONTACT_HIST_IM_ID est l'identifiant du contrat

    J'ai effectué une query qui permet de récupérer tous les noms associés à un contrat mais les noms sont en double et j'aimerais avoir les noms qu'une seule fois:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
      SELECT im_id,
        SUBSTR(SYS_CONNECT_BY_PATH(contact_name, ', '),2) contact_name
      FROM
        (SELECT DISTINCT(CONTACT_NAME),
          CONTACT_HIST_IM_ID as im_id,
          COUNT(*) OVER ( partition BY CONTACT_HIST_IM_ID ) im,
          ROW_NUMBER () OVER ( partition BY CONTACT_HIST_IM_ID order by contact_name) seq
        FROM FIDES_CONTACT_HIST_V
        WHERE CONTACT_HIST_IM_ID IS NOT NULL
        )
      WHERE seq               =im
        START WITH seq        =1
        CONNECT BY prior seq+1=seq
      AND prior im_id         =im_id;
    IM_ID CONTACT_NAME
    39 Constantin-Alin, Constantin-Alin, Constantin-Alin, Constantin-Alin, Constantin-Alin, Constantin-Alin, Constantin-Alin, Constantin-Alin, Constantin-Alin, Constantin-Alin, Georges, Georges, Georges, Georges, Georges, Georges, Georges, Georges, Georges, Georges, Maurizio, Maurizio, Maurizio, Maurizio, Maurizio, Maurizio, Maurizio, Maurizio, Maurizio, Maurizio, Michel, Michel, Michel, Michel, Michel, Michel, Michel, Michel, Michel, Michel, Mohammad Reza, Mohammad Reza, Mohammad Reza, Mohammad Reza, Mohammad Reza, Mohammad Reza, Mohammad Reza, Mohammad Reza, Mohammad Reza, Mohammad Reza, Pal, Pal, Pal, Pal, Pal, Pal, Pal, Pal, Pal, Pal


    Pourriez-vous m'aider à éviter les doublons car je ne sais pas comment faire même avec un DISTINCT ?

  2. #2
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Avec LISTAGG (suivant ta version de BDD)

    https://oracle-base.com/articles/12c...ncements-12cr2
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

  3. #3
    Membre chevronné
    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Décembre 2019
    Messages
    1 138
    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 138
    Points : 1 918
    Points
    1 918
    Par défaut
    Bonjour,

    Pourquoi utilises-tu un connect by? Y-a-t-il une notion de hiérarchie dans cette table? Si non, tu as juste un faire un select distinct sur les colonnes.

  4. #4
    Membre du Club
    Inscrit en
    Juin 2008
    Messages
    102
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 102
    Points : 47
    Points
    47
    Par défaut
    J'avais utilisé cela dans le passé pensant que c'était la meilleure solution à l'époque pour mes besoins.
    Par contre maintenant c'est vrai que ce n'est plus la meilleure solution.
    Par contre il faut quand même que je fusionne tous les contacts dans un même champs

  5. #5
    Membre du Club
    Inscrit en
    Juin 2008
    Messages
    102
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 102
    Points : 47
    Points
    47
    Par défaut
    Citation Envoyé par McM Voir le message
    Avec LISTAGG (suivant ta version de BDD)

    https://oracle-base.com/articles/12c...ncements-12cr2
    J'ai essayé cela:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT CONTACT_HIST_IM_ID as im_id, LISTAGG(CONTACT_NAME, ',') WITHIN GROUP (ORDER BY CONTACT_NAME) AS CONTACT_NAME
    FROM   FIDES_CONTACT_HIST_V
    GROUP BY CONTACT_HIST_IM_ID
    ORDER BY CONTACT_HIST_IM_ID;
    Mais le problème est toujours identique: j'ai toujours les doublons.

  6. #6
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Tu as suivi le lien Listagg distinct ?
    paramètre DISTINCT en 19c, sinon, ils donnent des exemples pour enlever les doublons (avec un sous-requête faisant un distinct, puis listagg dessus)

    si pas en 19c, alors ceci va fonctionner
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    select im_id, LISTAGG(CONTACT_NAME, ',') WITHIN GROUP (ORDER BY CONTACT_NAME) AS CONTACT_NAME
    FROM (
    SELECT DISTINCT CONTACT_HIST_IM_ID AS im_id, CONTACT_NAME FROM FIDES_CONTACT_HIST_V)
    GROUP BY im_id
    ORDER BY im_id
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

  7. #7
    Membre du Club
    Inscrit en
    Juin 2008
    Messages
    102
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 102
    Points : 47
    Points
    47
    Par défaut
    Merci beaucoup

  8. #8
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 936
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 936
    Points : 4 356
    Points
    4 356
    Par défaut
    Citation Envoyé par McM Voir le message
    Tu as suivi le lien Listagg distinct ?
    paramètre DISTINCT en 19c, sinon, ils donnent des exemples pour enlever les doublons (avec un sous-requête faisant un distinct, puis listagg dessus)
    Il y plusieurs choses dont il faut être conscient avec la technique du sous-query utilisant DISTINCT :
    - cela peut devenir coûteux sur de gros volumes et pousser à la création d'un index composé (ici sur CONTACT_HIST_IM_ID et CONTACT_NAME) s'il n'existe déjà,
    alors que souvent il existe déjà des index simples sur les champs concernés,
    - cela marche tant qu'on a besoin que d'un seul LISTAGG dans la requête originale.

    Une autre technique à connaître est celle qui consiste à profiter du fait que LISTAGG ne retourne pas les NULL,
    donc au lieu de faire le LISTAGG sur la colonne originale est de faire sur un calcul CASE qui retourne NULL si la valeur est égale à la suivante sur la partition par
    la clé triée par la colonne que l'on veut collecter:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CONTACT_NAME WHEN LEAD(CONTACT_NAME,1) OVER(PARTITION BY CONTACT_HIST_IM_ID ORDER BY CONTACT_NAME) THEN NULL ELSE CONTACT_NAME END
    

    Cela nécessite aussi une sous-requête car on ne peut avoir de fonction de fenêtrage à l'intérieur même du LISTAGG,
    mais l'avantage est que cela fonctionnera quelque soit le nombre de LISTAGG dont vous avez besoin dans le résultat final et souvent cela ré-utilise des index qui existent déjà,
    et donc il est aussi probable dans ce cas que cela retourne les premiers résultats plus rapidement (sur de gros volumes).



+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 20/02/2018, 11h43
  2. Réponses: 17
    Dernier message: 24/02/2016, 11h03
  3. concaténer plusieurs lignes dans un champs
    Par papoulouis dans le forum SQL
    Réponses: 10
    Dernier message: 30/01/2009, 20h08
  4. "concaténer" plusieurs lignes dans un seul champ
    Par djobert dans le forum Langage SQL
    Réponses: 3
    Dernier message: 02/12/2008, 18h00
  5. [JGraph] plusieurs lignes dans un même vertex
    Par smendou dans le forum 2D
    Réponses: 2
    Dernier message: 23/06/2008, 15h42

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