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 :

Transposer lignes en colonnes de façon dynamique


Sujet :

SQL Oracle

  1. #1
    Nouveau membre du Club
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2017
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Décembre 2017
    Messages : 66
    Points : 39
    Points
    39
    Par défaut Transposer lignes en colonnes de façon dynamique
    Bonjour,

    J'ai la table suivante :

    CLIENT DATE QTE
    A 01.05.2022 5
    A 01.06.2022 6
    A 01.07.2022 7
    B 01.05.2022 1
    B 01.06.2022 2

    Et je vouvrais obtenir ceci :

    CLIENT M1 M2 M3
    A 5 6 7
    B 1 2 0

    Et si après on arrive à tricher pour insérer une ligne d'entête (et donc convertir la date en format texte) pour obtenir ceci ce serait l'idéal :

    CLIENT M1 M2 M3
    01.05.2022 01.06.2022 01.07.2022
    A 5 6 7
    B 1 2 0


    Cependant, je ne peux pas connaître le nombre de colonnes à l'avance car chaque mois cela peut changer, le mois d'après, je peux très bien obtenir le résultat suivant :

    CLIENT DATE QTE
    A 01.05.2022 5
    A 01.06.2022 6
    A 01.07.2022 7
    A 01.08.2022 4
    A 01.09.2022 6
    A 01.10.2022 8

    Il faudrait donc que je puis passer la date en colonnes mais de façon dynamique.

    Merci.
    Bonne journée.

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

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 957
    Points : 4 386
    Points
    4 386
    Par défaut
    Il n'y a pas de PIVOT dynamique en SQL, par contre PIVOT XML peut le faire
    ou
    recourir un SQL dynamique (EXECUTE IMMEDIATE) où vous construirez vous-même la liste du IN()
    ou
    utiliser une des solutions existantes sur le Net et utilisant les Polymorphic Table Functions si votre version le permet.

  3. #3
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 109
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 109
    Points : 28 439
    Points
    28 439
    Par défaut
    Bonjour,

    Pour passer des lignes en colonne, il faut utiliser l'opérateur PIVOT.
    Toutefois, une requête retournera toujours un nombre de colonnes fixe correspondant à sa définition.
    Pour obtenir un nombre de colonnes variable, il faudra passer par une procédure qui construira dynamiquement la requête avant de l'exécuter.

  4. #4
    Nouveau membre du Club
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2017
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Décembre 2017
    Messages : 66
    Points : 39
    Points
    39
    Par défaut
    Merci, c'est ce que je pensais...

    Je vais essayer le EXECUTE IMMEDIATE alter table et construire mes colonnes en calculant le nombre de mois entre ma date max et min....

  5. #5
    Nouveau membre du Club
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2017
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Décembre 2017
    Messages : 66
    Points : 39
    Points
    39
    Par défaut
    Bonjour,

    J'ai essayé en voulant récupérer le nombre de mois à ajouter en cherchant ma plus petite date et ma plus grande mais j'ai un message d'erreur :
    [Error] PLS-00225 (212: 93): PLS-00225: subprogram or cursor 'NBMOIS' reference is out of scope
    C'est la première fois que je fais ça....

    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
    BEGIN
     
        DECLARE
     
             CURSOR curs IS (SELECT DISTINCT MONTHS_BETWEEN (MAX(DATE),MIN(DATE)) AS NB,
                                      MIN(DATE) AS DEBUT
                               FROM MaTable);
     
          BEGIN
     
            FOR i IN curs
            LOOP
               execute immediate 'alter table MaTable add ('||curs.DEBUT||' varchar2(50))'; 
            END LOOP;
     
          END;
     
     
    END;
    Le nombre de mois correspond au nombre de colonnes que je souhaiterais ajouter en partant de ma plus petite date.

    Merci.

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

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 957
    Points : 4 386
    Points
    4 386
    Par défaut
    le BEGIN extérieur n'est pas nécessaire et il faut ouvrir le CURSOR :
    avant de l'utiliser
    (et le fermer après la boucle)

  7. #7
    Nouveau membre du Club
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2017
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Décembre 2017
    Messages : 66
    Points : 39
    Points
    39
    Par défaut
    Merci !


    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
    DECLARE
     
             CURSOR curs IS (SELECT DISTINCT MONTHS_BETWEEN (MAX(DATE),MIN(DATE)) AS NB,
                                      MIN(DATE) AS DEBUT
                               FROM MaTable);
     
     
          BEGIN
            OPEN curs; 
     
            FOR i IN curs
     
            LOOP
               execute immediate 'alter table MaTable add ('||i.DEBUT||' DATE)'; 
            END LOOP;
     
            CLOSE curs;
     
          END;
    J'ai encore l'erreur suivante :
    [Error] Execution (1: 1): ORA-06511: PL/SQL: cursor already open
    ORA-06512: at line 3
    ORA-06512: at line 11

  8. #8
    Membre chevronné
    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Décembre 2019
    Messages
    1 159
    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 159
    Points : 1 949
    Points
    1 949
    Par défaut
    Un curseur implicite FOR LOOP n'a pas besoin d'être ouvert et fermé, c'est fait implicitement par la boucle FOR LOOP.

  9. #9
    Nouveau membre du Club
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2017
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Décembre 2017
    Messages : 66
    Points : 39
    Points
    39
    Par défaut
    Citation Envoyé par vanagreg Voir le message
    Un curseur implicite FOR LOOP n'a pas besoin d'être ouvert et fermé, c'est fait implicitement par la boucle FOR LOOP.

    OK merci mais il me reste encore cette erreur :

    ORA-06550: line 17, column 93:
    PLS-00201: identifier 'DEBUT' must be declared
    ORA-06550: line 17, column 12:
    Je ne comprends pas comment lui faire ajouter mes 3 colonnes....

  10. #10
    Membre chevronné
    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Décembre 2019
    Messages
    1 159
    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 159
    Points : 1 949
    Points
    1 949
    Par défaut
    Un identifiant de colonne ne peut pas commencer par un chiffre (bien sûr je proscris d'emblée l'utilisation de guillemets pour le nommage des identifiants). Donc si tu veux ajouter une colonne à partir d'une date, fais qqch comme

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     execute immediate 'alter table MaTable add (D'||to_char(i.DEBUT, 'yyyymmdd')||' DATE)';
    Au fait, tu as des colonnes qui s'appelent DATE, mais c'est un mot réservé, donc ce n'est pas possible, mais je suppose que c'est une version "simplifiée" de ton code.

  11. #11
    Nouveau membre du Club
    Femme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2017
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Décembre 2017
    Messages : 66
    Points : 39
    Points
    39
    Par défaut
    Bonjour,

    Oui oui, j'ai simplifié mon code !

    Au cas où....si ça peut servir à qqn... voici comment j'ai enfin réussi à créer dynamiquement mes colonnes. Pour mon exemple 3 colonnes se créeront automatiquement. Le nombre de colonnes à créer dépend de la période donnée à la base :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    SELECT DISTINCT MONTHS_BETWEEN (MAX (DATE),MIN (DATE))+1, max(DATE)
            INTO nb_mois, datemax
            FROM MaTable;
     
            FOR i IN 1 .. nb_mois
            LOOP
                EXECUTE IMMEDIATE
                'alter table MaTable add (COL_'
                || (i)
                || ' NUMBER)';
            END LOOP;
    Je suis ensuite venue remplir le contenu de ces colonnes avec un EXECUTE IMMEDIATE UPDATE.

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

Discussions similaires

  1. Transposer lignes en colonnes
    Par g_marpillat dans le forum Langage SQL
    Réponses: 5
    Dernier message: 21/09/2017, 16h32
  2. [AC-2007] probleme de requete sql transposer ligne et colonne
    Par nicogef dans le forum Access
    Réponses: 1
    Dernier message: 16/06/2015, 19h38
  3. [XL-2010] Transposer ligne en colonne et création de doublons
    Par hatem_rc dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 15/11/2013, 00h04
  4. [XL-2007] Transposer lignes et colonnes contenant des formules
    Par cdaumas78 dans le forum Conception
    Réponses: 11
    Dernier message: 24/02/2013, 21h05
  5. proc tabulate : transposer ligne et colonne
    Par Lou12 dans le forum SAS Base
    Réponses: 1
    Dernier message: 26/05/2010, 13h20

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