web-dev-qa-db-fra.com

Existe-t-il une requête Oracle SQL qui regroupe plusieurs lignes en une seule ligne?

J'ai une table qui ressemble à ceci:

A 1 
A 2 
B 1 
B 2

Et je veux produire un jeu de résultats qui ressemble à ceci:

A 1 2 
B 1 2

Existe-t-il une instruction SQL qui fera cela? J'utilise Oracle.

Questions connexes:

31
user128807

Cela dépend de la version d'Oracle que vous utilisez. S'il prend en charge la fonction wm_concat (), vous pouvez simplement faire quelque chose comme ceci:

SELECT field1, wm_concat(field2) FROM YourTable GROUP BY field2;

wm_concat () fonctionne essentiellement comme group_concat () dans MySQL. Cela peut ne pas être documenté, alors lancez ye olde sqlplus et voyez s'il est là.

S'il n'est pas là, alors vous voudrez implémenter vous-même quelque chose d'équivalent. Vous pouvez trouver des instructions sur la façon de procéder dans la page d'agrégation de chaînes sur Oracle-base.com.

28
John Hyland

Sujet assez ancien, mais cela pourrait aider les autres depuis qu'Oracle s'est amélioré entre-temps.

La fonction LISTAGG est ce que vous recherchez (en 11g au moins)

21
user1973071

Dans Oracle 10g+:

SELECT  *
FROM    (
        SELECT  *
        FROM    mytable
        MODEL
        PARTITION BY
                (grouper)
        DIMENSION BY
                (ROW_NUMBER() OVER (PARTITION BY grouper ORDER BY id) AS rn)
        MEASURES
                (val, val AS group_concat, 0 AS mark)
        RULES SEQUENTIAL ORDER (
                group_concat[rn > 1] ORDER BY rn = group_concat[CV() - 1] || ', ' || val[CV()],
                mark[ANY] ORDER BY rn = PRESENTV(mark[CV() + 1], 0, 1)
                )
        )
WHERE   mark = 1
ORDER BY
        grouper

Voir cet article dans mon blog pour des explications:

9
Quassnoi

Essayez quelque chose comme:

SELECT
    field1,
    RTRIM(REPLACE(REPLACE(XMLAgg(XMLElement("x", field2) ORDER BY field2), '<x>'), '</x>', ' ')) AS field2s
  FROM yourTable
  GROUP BY field1

Librement inspiré par une réponse trouvée dans ce forum Oracle .

EDIT: cette solution a prouvé très ressources intensives avec des demandes impliquant quelque chose comme 105 Lignes. J'ai fini par remplacer cela par des fonctions d'agrégation personnalisées comme suggéré par John .

5
Mac

Si vous avez 10g, vous devez passer par la fonction ci-dessous:

CREATE OR REPLACE FUNCTION get_separated_value (input_val  in  number)
  RETURN VARCHAR2
IS
  return_text  VARCHAR2(10000) := NULL;
BEGIN
  FOR x IN (SELECT col2 FROM table_name WHERE col1 = input_val) LOOP
    return_text := return_text || ' ' || x.col2 ;
  END LOOP;
  RETURN return_text;
END;
/

Ainsi, vous pouvez faire comme:

select col1, get_separated_value(col1) from table_name

Violon ici

Si vous avez Oracle 11g, vous pouvez utiliser listagg :

SELECT 
    age,
    LISTAGG(name, ' ') WITHIN GROUP (ORDER BY name) "names"
FROM table_x
GROUP BY age

Violon ici pour Listagg

4
hsuk

Fonctions d'agrégation définies par l'utilisateur: http://www.adp-gmbh.ch/ora/sql/user_def_agg.html

Copiez/collez et utilisez-le. Fonctionne sur 9i.

2
jva
SELECT a , COLLECT(b) FROM foo GROUP BY a

très utile lorsqu'il est utilisé dans pl/sql - peut être casté dans une collection définie par l'utilisateur.

2
haki