web-dev-qa-db-fra.com

Concaténer plusieurs lignes dans un tableau avec SQL sur PostgreSQL

J'ai une table construite comme ça:

oid | identifier | value
1   | 10         | 101
2   | 10         | 102
3   | 20         | 201
4   | 20         | 202
5   | 20         | 203

J'aimerais interroger cette table pour obtenir un résultat comme celui-ci:

identifier | values[]
10         | {101, 102}
20         | {201, 202, 203}

Je ne peux pas trouver un moyen de faire ça. Est-ce possible ? Comment ?

Merci beaucoup.

31
Tyn

Ceci est une version intégrée de Postgres depuis quelques versions, vous n’avez donc plus besoin de définir la vôtre, le nom est array_agg().

test=> select array_agg(n) from generate_series(1,10) n group by n%2;
  array_agg   
--------------
 {1,3,5,7,9}
 {2,4,6,8,10}

(c'est Postgres 8.4.8).

Notez que ORDER BY n'est pas spécifié. L'ordre des lignes de résultat dépend donc de la méthode de regroupement utilisée (ici, hash), c'est-à-dire qu'elle n'est pas définie. Exemple:

test=> select n%2, array_agg(n) from generate_series(1,10) n group by (n%2);
 ?column? |  array_agg   
----------+--------------
        1 | {1,3,5,7,9}
        0 | {2,4,6,8,10}

test=> select (n%2)::TEXT, array_agg(n) from generate_series(1,10) n group by (n%2)::TEXT;
 text |  array_agg   
------+--------------
 0    | {2,4,6,8,10}
 1    | {1,3,5,7,9}

Maintenant, je ne sais pas pourquoi vous obtenez {10,2,4,6,8} et {9,7,3,1,5}, puisque generate_series() devrait envoyer les lignes dans l’ordre.

55
peufeu

Vous devez créer une fonction d'agrégat, par exemple.

CREATE AGGREGATE array_accum (anyelement)
(
sfunc = array_append,
stype = anyarray,
initcond = '{}'
);

puis

SELECT identifier, array_accum(value) AS values FROM table GROUP BY identifier;

HTH

16
Johannes Weiss

Voici le code pour la sortie demandée.

select identifier, array_agg(value)
from (
  values
    (1   , 10         , 101),
    (2   , 10         , 102),
    (3   , 20         , 201),
    (4   , 20         , 202),
    (5   , 20         , 203)
  ) as tab (oid, identifier, value)
group by identifier
order by identifier;
1
Mikkel

Exemple simple: chaque cours comporte de nombreuses leçons, donc si je lance le code ci-dessous:

SELECT
  lessons.course_id AS course_id,
  array_agg(lessons.id) AS lesson_ids
FROM lessons
GROUP BY
  lessons.course_id
ORDER BY
  lessons.course_id

j'obtiendrais le résultat suivant:

┌───────────┬──────────────────────────────────────────────────────┐
│ course_id │                   lesson_ids                         │
├───────────┼──────────────────────────────────────────────────────┤
│         1 │ {139,140,141,137,138,143,145,174,175,176,177,147,... │
│         3 │ {32,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,... │
│         5 │ {663,664,665,649,650,651,652,653,654,655,656,657,... │
│         7 │ {985,984,1097,974,893,971,955,960,983,1045,891,97... │
│       ...                                                        │
└───────────┴──────────────────────────────────────────────────────┘
0
Sergio Belevskij