Précédent   Forum des professionnels en informatique > Bases de données > Oracle > SQL
SQL Forum d'entraide sur le SQL pour Oracle
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 16/06/2011, 14h01   #1
Candidat au titre de Membre du Club
 
Inscription : juin 2008
Messages : 51
Détails du profil
Informations forums :
Inscription : juin 2008
Messages : 51
Points : 13
Points : 13
Par défaut Transposer une table (colonne -> ligne)

Bonjour,

Je tiens d'abord à m'excuser si ce sujet a déja eu une réponse, mais ayant passé toute la matinée sur le forum je n'ai pas trouver de répons eà mon interrogation d'où la création de cette discussion;

J'ai une table Test avec les valeur:

Code :
1
2
3
4
5
CREATE TABLE test_irf
(
    id_pers number(11),
    mnt     number( 9)
);
echantillon test :
Code :
1
2
3
4
5
INSERT INTO test_irf VALUES (1, 10);
INSERT INTO test_irf VALUES (1, 11);
INSERT INTO test_irf VALUES (1, 12);
INSERT INTO test_irf VALUES (2,  1);
INSERT INTO test_irf VALUES (2,  2);
J'aimerai savoir comment transposer cette table pour obtenir
1 | 10 | 11 | 12
2 |  1 |  2 | null
Je sèche !

Merci beaucoup !
twixi est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/06/2011, 14h22   #2
Membre Expert
 
Inscription : août 2008
Messages : 1 271
Détails du profil
Informations forums :
Inscription : août 2008
Messages : 1 271
Points : 1 929
Points : 1 929
Recherche pivot sur le forum, mais compte tenu de ton exemple ça ne fonctionnera pas, le SQL est un langage statique qui doit connaître à l'avance le nombre de colonne.
Donc pivote les lignes en colonnes côté applicatif ou génère la requête pivot en déterminant précédemment le nombre de colonnes à afficher.
Si tu dois le faire en PL/SQL regarde pivot de tkyte.

Sinon regarde peut être du côté de String Aggregation Techniques, mais ça n'est pas du pivot.
skuatamad est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/06/2011, 14h55   #3
Membre confirmé
 
Homme Grégoire MARTIN
Ingénieur développement logiciels
Inscription : janvier 2011
Messages : 128
Détails du profil
Informations personnelles :
Nom : Homme Grégoire MARTIN
Âge : 32
Localisation : France, Hauts de Seine (Île de France)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : Finance

Informations forums :
Inscription : janvier 2011
Messages : 128
Points : 225
Points : 225
Ok c'est un peu tordu , mais l'astuce c'est de générer un chainage entre les lignes puis de passer par une lecture hierarchique et de ne garder que le plus grand path .

Code :
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
 
WITH test_irf
AS
(
SELECT 1 AS id_pers , 10 AS mnt FROM DUAL UNION ALL
SELECT 1            , 11        FROM DUAL UNION ALL
SELECT 1            , 12        FROM DUAL UNION ALL
SELECT 2            , 1         FROM DUAL UNION ALL
SELECT 2            , 2         FROM DUAL 
)
SELECT id_pers||'|'||mnt_list
FROM (
      SELECT
         id_pers,
         substr(SYS_CONNECT_BY_PATH(mnt, '|'),2) mnt_list
      FROM
         (
         SELECT id_pers,
                mnt,
                count(*) OVER ( partition BY id_pers ) cnt,
                ROW_NUMBER () OVER ( partition BY id_pers ORDER BY mnt) seq
         FROM   test_irf
         WHERE  mnt IS NOT NULL
         )
      WHERE seq=cnt
      START WITH seq=1
      CONNECT BY PRIOR seq+1 = seq
      AND PRIOR id_pers = id_pers
    )
;
Il doit y avoir des façons plus propre, d'ailleurs je suis preneur
ORA-007 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/06/2011, 15h09   #4
Candidat au titre de Membre du Club
 
Inscription : juin 2008
Messages : 51
Détails du profil
Informations forums :
Inscription : juin 2008
Messages : 51
Points : 13
Points : 13
Juste une petite correction,

le résultat attendu était plutôt de récupérer le résultats dans des colonnes différentes.

ID_PERS  | MNT_1 | MNT_2 | MNT_3 |
----------------------------------
1        | 10    | 11    |  12   |
2        | 1     | 2     |  null |
twixi est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/06/2011, 15h19   #5
Membre Expert
 
Inscription : août 2008
Messages : 1 271
Détails du profil
Informations forums :
Inscription : août 2008
Messages : 1 271
Points : 1 929
Points : 1 929
Citation:
Envoyé par twixi Voir le message
le résultat attendu était plutôt de récupérer le résultats dans des colonnes différentes.
J'avais bien compris, relis mon message !
skuatamad est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/06/2011, 15h21   #6
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 684
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 684
Points : 10 433
Points : 10 433
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
Comme skuatamad vous l'a indiqué, il faut faire un pivot :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
WITH SR AS
(
SELECT id_pers, mnt
     , row_number() over(partition BY id_pers ORDER BY mnt ASC) AS rn
  FROM test_irf
)
  SELECT id_pers
       , max(case rn when 1 then mnt end) AS mnt_1
       , max(case rn when 2 then mnt end) AS mnt_2
       , max(case rn when 3 then mnt end) AS mnt_3
    FROM SR
GROUP BY id_pers
ORDER BY id_pers ASC;
 
   ID_PERS      MNT_1      MNT_2      MNT_3
---------- ---------- ---------- ----------
         1         10         11         12
         2          1          2
__________________
Email : http://scr.im/waldar
Waldar est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/06/2011, 15h29   #7
Candidat au titre de Membre du Club
 
Inscription : juin 2008
Messages : 51
Détails du profil
Informations forums :
Inscription : juin 2008
Messages : 51
Points : 13
Points : 13
Merci beaucoup pour ta réponse skuatamad. Il n'est donc pas possible d'obtenir ce que je veux .

A vrai dire mon problème est le suivant :


J'ai 12 lignes par ID_PERS (1 ligne correspond à un mois) et j'aimerai donc le transposer. Le nombre de colonne est à présent fixé.

Je voudrais créer un top=1 pour les id_pers ayant le montant > 1500 durant 3 mois consécutifs?

Je ne vois pas comme faire là ...
twixi est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/06/2011, 17h15   #8
Membre Expert
 
Avatar de pacmann
 
Homme Pacman Pacman
Business analyst
Inscription : juin 2004
Messages : 1 417
Détails du profil
Informations personnelles :
Nom : Homme Pacman Pacman
Âge : 31
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : Business analyst
Secteur : Finance

Informations forums :
Inscription : juin 2004
Messages : 1 417
Points : 2 309
Points : 2 309
Salut !

Tu peux utiliser les fonctions analytiques pour calculer sur chaque ligne une somme selon un ordre et dans un group.

Code :
1
2
 
SUM(mnt) OVER (PARTITON BY id_pers ORDER BY tadate ROWS 3 PRECEDING )
Cela te donnera pour chaque ligne la somme des montants sur une fenêtre de 3 précédents.

Ensuite, tu fais une sur-requête sur le résultat pour filtrer les lignes dont la somme cumulée est supérieure à 1500...
__________________

(c'est ma photo)
Paku, Paku !
Pour les jeunes incultes : non, je ne suis pas un pokémon...

Le pacblog : http://pacmann.over-blog.com/
pacmann est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 16/06/2011, 18h04   #9
Candidat au titre de Membre du Club
 
Inscription : juin 2008
Messages : 51
Détails du profil
Informations forums :
Inscription : juin 2008
Messages : 51
Points : 13
Points : 13
Merci Waldar !
Ton exemple réponds parfaitement à mon besoin initial !

Merci pacmann !
C'est exactement ce que je cherchais !
twixi est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 19h10.


 
 
 
 
Partenaires

Hébergement Web