32 votes

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 résultat qui ressemble à ceci:

A 1 2 
B 1 2

Est-il une instruction SQL qui va le faire? Je suis de l'utilisation d'Oracle.

Questions connexes:

28voto

John Hyland Points 4578

Cela dépend de la version d'Oracle que vous utilisez. Si elle prend en charge la wm_concat() de la fonction, alors 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() de MySQL. Il peut ne pas être documentés, donc le feu au ye olde sqlplus et voir si il y est.

Si elle n'est pas là, alors vous aurez envie de mettre en œuvre quelque chose d'équivalent vous-même. Vous pouvez trouver des instructions sur la façon de faire dans la chaîne de l'agrégation de la page à oracle-base.com.

23voto

user1973071 Points 151

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)

9voto

Quassnoi Points 191041

En 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:

5voto

Mac Points 4570

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 cet Oracle forum.

EDIT: cette solution s'est avérée très intensive des ressources avec les demandes concernant à quelque chose comme 105 lignes. J'ai fini par le remplacer par la coutume, les fonctions d'agrégation proposée par John.

4voto

hsuk Points 3221

Si vous avez 10g, alors 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 disposez d'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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X