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 :

Problème requête pivot [11g]


Sujet :

SQL Oracle

  1. #1
    Membre éprouvé
    Homme Profil pro
    Analyse système
    Inscrit en
    Juin 2013
    Messages
    971
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Analyse système
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2013
    Messages : 971
    Par défaut Problème requête pivot
    Bonjour,
    j'ai une requête avec beaucoup de résultat ( d'environ une centaine de colonne au bas mot), initialement elle me retourné qu'une seul ligne par identifiant, mais en rajoutant les dernière colonne, elle me rajoute plusieurs lignes ( ce qui est logique car pour une personne, on peut avoir plusieurs résultats possible).

    Seulement on m'a "imposé" d'avoir une seul ligne, par identifiant, j'ai donc tenté une requête pivot, avec juste l'identifiant et les colonnes que j'ai rajouté, mais pareil, j'ai toujours plusieurs lignes.

    Est il possible de faier en sorte d'avoir qu'une seul ligne par identifiant, sachant qu'il y a plusieurs mode pour une personne et plusieurs qualifications?
    Un exemple tout bête avec la copie d'écran:
    123456 : au 01/01/17 (pivot.png) tous les cadres dont l'identifiant est 123456 ont un mode par internet
    au 01/01/17 tous les etams et ouvriers dont l'identifiant est 123456 on un mode papier

    Personnellement je trouve cela hautement improbable de faire cela sur une ligne, quand on à un mode différent, non?
    merci à vous

  2. #2
    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 android59 Voir le message
    Personnellement je trouve cela hautement improbable de faire cela sur une ligne, quand on à un mode différent, non?
    Cette question ne s'adresse qu'à vos utilisateurs / métiers / PO, je ne vois pas trop ce que vous attendez du forum ici.
    Techniquement c'est possible - on peut afficher la première, la dernière, toutes les valeurs - fonctionnellement ce n'est vraiment pas à nous (ni à vous a priori) de décider.

  3. #3
    Membre éprouvé
    Homme Profil pro
    Analyse système
    Inscrit en
    Juin 2013
    Messages
    971
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Analyse système
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2013
    Messages : 971
    Par défaut
    Bonjour,
    en fait justement c'était pour savoir comment faire car je ne sais pas trop comment faire cela, j'ai essayé avec un pivot mais sans succès :s

    En reprenant l'image pivot.png c'est possible de tout mettre sur une ligne ?

    Pour information, le but final est de réaliser un publipostage

    merci à vous !

  4. #4
    McM
    McM est déconnecté
    Expert confirmé

    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
    Billets dans le blog
    4
    Par défaut
    J'ai pas bien compris, et sans requête c'est compliqué de trouver.
    A priori si tu ne veux qu'une seule ligne, faudrait utiliser un GROUP BY, et des SUM((DECODE(..)) ou des MAX() pour les colonnes

  5. #5
    Membre éprouvé
    Homme Profil pro
    Analyse système
    Inscrit en
    Juin 2013
    Messages
    971
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Analyse système
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2013
    Messages : 971
    Par défaut
    Autant pour moi, j'avais justement préparé une petite requete pour l'exemple :
    initialement j'ai une requête de ce style là:

    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
     
    select ta.identificant,
    nom,
    prenom,
    age,
    ...
    ...
    ....
    ...
    ....
    ...
    t4.valeur as valeur, --etam, cadre ou ouvrier
    tpro.valeur as mode2, --internet ou papier
    t2.datedebut as date_debut,
    t2.datefin as date_fin
     
    FROM personne ta
    left outer join mode1 t2 on ta.id=t2.idrefta
    left outer join mode2 tpro on  tpro.id=t2.idreft2
    left outer join qualif t4 on t4.id=t2.idreft4
    inner join ....
    inner join ....
    inner join ....
     
    where .......
    and ta.identificant ='123456'
    and..........
    and..........
    au début elle ne me retourne qu'une ligne, avec tout mes champs. Lorsque je met la condition :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    and ta.identificant in ('123456','123654','6599','565555')
    je ne dois avoir que 4 lignes or en rajoutant mes dernieres colonnes j'ai des doublons car pour une personne ( pour l'id 123456) on peut avoir plusieurs modes , donc je me suis dis c'est logique qu'il y ai plusieurs lignes , car la personne a plusieurs modes, mais on m'a imposé de n'avoir qu'une ligne par identifiant, tout en conservant mes données et c'est là où je sèche :s

    voici le code que j'ai utilise pour illustré mes images :
    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
     
    select *
    from 
    (
    select ta.identificant,
    t4.valeur as valeur, --etam, cadre ou ouvrier
    tpro.valeur as mode2, --internet ou papier
    t2.datedebut as date_debut,
    t2.datefin as date_fin
     
    FROM personne ta
    left outer join mode1 t2 on ta.id=t2.idrefta
    left outer join mode2 tpro on  tpro.id=t2.idreft2
    left outer join qualif t4 on t4.id=t2.idreft4
    where .......
    and ta.identificant in ('123456','789101112')
    and..........
    and..........
    )
    pivot (
    max(valeur) --t4.valeur donc 
    for valeur in ('ETAM','CADRE','OUVRIER')
     
    )
    order by 1
    Merci

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

    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
    Billets dans le blog
    4
    Par défaut
    Faut savoir ce qu'on te demande et ce qu'il faut gérer comme cas.

    Exemple : Avec listagg, tu auras la liste des données.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    select ta.identificant,
    listagg(t4.valeur, ' ') within group (ORDER BY t4.valeur) as valeur, --etam, cadre ou ouvrier
    listagg(tpro.valeur, ' ') within group (ORDER BY tpro.valeur) as mode2, --internet ou papier
    MIN(t2.datedebut) as date_debut,
    MAX(t2.datefin) as date_fin
    FROM personne ta
    left outer join mode1 t2 on ta.id=t2.idrefta
    left outer join mode2 tpro on  tpro.id=t2.idreft2
    left outer join qualif t4 on t4.id=t2.idreft4
    where .......
    and ta.identificant in ('123456','789101112')
    GROUP BY ta.identifiant
    Pour les dates, je sais pas si elle sont à associer aux valeurs ou pas, mais tu pourrais faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    listagg(t4.valeur ||'['|| to_char(t2.datedebut, 'DD.MM.RRRR') ||'-'|| to_char(t2.datefin, 'DD.MM.RRRR')||']', ' ') within group (ORDER BY t4.valeur) as valeur, --etam, cadre ou ouvrier [datedeb-datefin]

  7. #7
    Membre éprouvé
    Homme Profil pro
    Analyse système
    Inscrit en
    Juin 2013
    Messages
    971
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Analyse système
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2013
    Messages : 971
    Par défaut
    C'est pas mal en effet, merci.

    Oui les date de début et de fin sont associés aux valeurs

  8. #8
    Membre éprouvé
    Homme Profil pro
    Analyse système
    Inscrit en
    Juin 2013
    Messages
    971
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Analyse système
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2013
    Messages : 971
    Par défaut
    Bonjour,

    ça marche bien merci, mais je suis face à un autre problème, on doit utilisé un groupby avec cette fonction, seulement dans ma grosse requête, j'ai plein de sous-requete du genre :
    exemple1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    NVL((
    select t2.libelle
    from tablecode t2 
    where t2.valeur=fonction(ta.id, -1,sysdate, '123456')
    and t2.idreft3=98
    ),'-') as "123456",
    ----
    -----
    ou des zone calculé comme :

    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
     
    (
        select SUM(salaire)
        from tabledate t1
        where t1.idref=rec.idrefEnt 
        and champdate in (
        concat(to_char(sysdate, 'yyyy')-3,'M11'),
        concat(to_char(sysdate, 'yyyy')-3,'M12')
        )
        group by ...
    -
    ( 
        select (total_brut) 	 
        FROM  rec t1 
        inner join annee c1 on c1.id = t1.idrefc1
        where t1.idreftableEnt=tableEnt.id
        and  c1.annee=to_char(sysdate, 'yyyy')-3
    ) as ecart
    j'ai essayé de les mettres tel quel mais si je met rien qu'un morceau de code comme dans l'exemple 1, il me met une erreur du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ORA-22818: expressions de sous-requête non autorisées ici
    Y a t-il un moyen de pallier à ce genre de problème?

    Merci à vous

  9. #9
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 952
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 952
    Par défaut
    Faites vos nouvelles agrégations dans des sous requêtes corrélées comme pour les anciennes, et donc plus besoin de GROUP BY.

  10. #10
    Membre Expert
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Septembre 2016
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2016
    Messages : 939
    Par défaut
    Citation Envoyé par android59 Voir le message
    on doit utilisé un groupby avec cette fonction, seulement dans ma grosse requête, j'ai plein de sous-requete du genre [...]
    Sans vouloir te vexer il faut que tu saches que tu es très brouillon dans ta façon d'aborder les problèmes.

    Essaie de penser que ton code va être une "boite noire".
    Alors tu va mettre au propre les réponses à :
    1- Qu'est ce qui doit en sortir ?
    2- De quoi as t'on besoin en entrée ?
    Ça c'est la base de la réflexion AVANT d'essayer de faire.

    Pourquoi je dis ça ? Fais relire le post, depuis le début, à un pote.

    De plus ce que je te propose va t'éviter de trainer en début de réflexion
    "on doit utiliser" : pourquoi cette obligation ?
    "cette fonction" : c'est une procédure, une fonction, un script, une vue, une requête ?

    Pour venir à ta question : "j'ai plein de sous-requêtes" et "il me met une erreur"
    Les CTE -l'usage du mot clé WITH- peuvent aider.
    voir : https://oracle-base.com/articles/misc/with-clause

    La présentation du code est un gage de maintenabilité.

  11. #11
    Membre éprouvé
    Homme Profil pro
    Analyse système
    Inscrit en
    Juin 2013
    Messages
    971
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Analyse système
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2013
    Messages : 971
    Par défaut
    Merci pour ton retour.
    Justement ces premières questions je me les suis posé à l'origine, avant d'établir la requête, c'est une requête qui sera utilisé en publipostage. Lorsque j'ai commencé la requête, ça été rapide puisque les champs a récupéré sont utilisé dans d'autres requêtes.

    skuatamad j'ai réussi à résoudre une partie du problème , merci .


    Un dernier soucis se présente à moi, j'ai tenté de le résoudre en utilisant la méthode que préconise skuatamad , mais c'est plus compliqué, car là je dois reprendre une liste de champs (5 champs) mais les 7 dernières lignes à la date la plus récentes, par identifiant.

    Par exemple pour l'identifiant 66598 je dois avoir :

    66598 cadre mode1 25/12/2019
    66598 cadre mode2 25/12/2019
    66598 etam mode1 25/12/2019
    66598 etam mode2 25/12/2019
    66598 etam mode3 25/12/2019
    66598 cadre mode3 25/12/2019
    66598 ouvrier mode1 25/12/2019

    pour cela Michel.Priori, j'ai fais, en utilisant justement les CTE, lorsque je suis tombé dessus :
    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 * from
    (
    SELECT
        t1.identifiant,
        t3.valeurNotif               AS college,
        t2.datedebut   AS datedebut,
        t2.datefin     AS datefin,
        t4.valeurNotif2         AS valeur,
        t2.datecreation
    FROM    table1 t1
        INNER JOIN table2  t2 ON t1.x503_id = t2.x503_id
        INNER JOIN table3 t3 ON t3.id = t2.coll_id
        INNER JOIN table4 t4 ON t4.id = t2.mpce_id
    WHERE
        t1.identifiant= '66598 '   --j'ai mis cette condition car j'ai test cette requête à part, après je dois l'intégrer à ma grosse requête donc j'enleverais la condition et la 
    jointure
        --and t2.id=ta.id lorsque j'utilise cette jointure, pour l'intégrer à ma requête originel, il me retourne une erreur en me disant ta.id identificateur non valide
         t2.datefin is not null
    ORDER BY
        t2.datecreation DESC   --j'ai mis desc pour m'afficher directement les enregistrement à la date la plus recente
    )where rownum<7
    avec ce code, ça marche parfaitement, mais je ne sais pas l'intégré à ma requête d'origine.
    J'ai donc tenté avec ce morceau de code:

    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
     
    SELECT
        t1.identifiant,
        t3.valeur   AS college,
        t2.datedecreation
    FROM    table1 t1
        INNER JOIN table2  t2 ON t1. = t2.
        INNER JOIN table3 t3 ON t3.id = t2.idreftble3
        INNER JOIN table4 t4 ON t4.id = t2.idreftble3
    WHERE
    t1.identifiant = '66598 '
    and t2.datedecreation in
    (
        select max(t2.datedecreation)
        from table2  t2
        where t2.id = t1.id
     
    )
    order by t2.datedecreation desc
    mais il ne m'affiche qu'une seul ligne :
    66598 cadre mode1 25/12/2019

    Merci beaucoup

  12. #12
    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
    Regardez du côté de la fonction ROW_NUMBER :
    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
    with cte_base as
    (
    SELECT
        t1.identifiant,
        t3.valeur   AS college,
        t2.datedecreation,
        row_number() over(partition by t1.identifiant order by t2.datedecreation desc) as rn
    FROM    table1 t1
        INNER JOIN table2  t2 ON t1. = t2.
        INNER JOIN table3 t3 ON t3.id = t2.idreftble3
        INNER JOIN table4 t4 ON t4.id = t2.idreftble
    )
    select identifiant, college, datedecreation
      from cte_base
     where rn <= 7;

  13. #13
    Membre éprouvé
    Homme Profil pro
    Analyse système
    Inscrit en
    Juin 2013
    Messages
    971
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Analyse système
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2013
    Messages : 971
    Par défaut
    merci beaucoup , jusque là ça marche tres bien,
    j'ai réussi à l'adapter à ma grosse requête et le résultat attendu est là .

    J'ai juste rajouter à la fin (en rajoutant une valeur):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        select listagg(identifiant||'-'||college||'-'||datefin||'-'||datedecreation, ' ') within group (ORDER BY datedecreation)
      from cte_base
     where rn <= 7
     and identifiant = t1......  --ma jointure est ici avec ma requête
    un grand merci à vous

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

Discussions similaires

  1. Problème: Requête utilisant NOT IN
    Par fages dans le forum Langage SQL
    Réponses: 4
    Dernier message: 04/05/2004, 10h18
  2. erreur3073 Problème requête
    Par amel123456789 dans le forum Langage SQL
    Réponses: 8
    Dernier message: 01/04/2004, 10h15
  3. Problème requête qui renvoie plusieurs
    Par dai.kaioh dans le forum Langage SQL
    Réponses: 6
    Dernier message: 01/04/2004, 10h07
  4. Problème requête avec UNION et ORDER BY
    Par Yann21 dans le forum Langage SQL
    Réponses: 12
    Dernier message: 12/12/2003, 11h02
  5. Réponses: 8
    Dernier message: 23/10/2003, 16h22

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