Создать массив в SELECT - PullRequest
6 голосов
/ 21 марта 2012

Я использую PostgreSQL 9.1, и у меня есть эта структура данных:

A     B
-------
1     a
1     a
1     b
1     c
1     c
1     c
1     d
2     e
2     e

Мне нужен запрос, который дает такой результат:

1    4     {{c,3},{a,2},{b,1},{d,1}}
2    1     {{e,2}}

A = 1, всего 4 строки с A = 1, частичное число (3 строки со значением c, 2 строки со значением, .....)

  • Отдельные значения столбца "A"
  • Количество всех строк, связанных со значением «A»
  • Массив содержит все элементы, относящиеся к значению "A" и относительному количеству самого себя

Сортировка, необходимая для массива, основана на количестве каждой группы (как в примере 3,2,1,1).

Ответы [ 3 ]

9 голосов
/ 21 марта 2012

Это должно помочь:

SELECT a
     , sum(ab_ct)::int AS ct_total
     , count(*)::int   AS ct_distinct_b
     , array_agg(b || ', ' || ab_ct::text) AS b_arr
FROM  (
    SELECT a, b, count(*) AS ab_ct
    FROM   tbl
    GROUP  BY a, b
    ORDER  BY a, ab_ct DESC, b  -- append "b" to break ties in the count
    ) t
GROUP  BY a
ORDER  BY ct_total DESC;

Возвращает:

  • ct_total: общее количество b за a.
  • ct_distinct_b: число различных b на a.
  • b_arr: массив b плюс частота b, отсортированный по частоте b.

Упорядочено по общему количеству b на a.

В качестве альтернативы вы можете использовать предложение ORDER BY в совокупном вызове в PostgreSQL 9.0 или новее.Как:

SELECT a
     , sum(ab_ct)::int AS ct_total
     , count(*)::int   AS ct_distinct_b
     , array_agg(b || ', ' || ab_ct::text <b>ORDER BY a, ab_ct DESC, b</b>) AS b_arr
FROM  (
    SELECT a, b, count(*) AS ab_ct
    FROM   tbl
    GROUP  BY a, b
    ) t
GROUP  BY a
ORDER  BY ct_total DESC;

Может быть, яснее.Но обычно это медленнее.И сортировка строк в подзапросе работает для простых запросов, подобных этому.Дополнительные пояснения:

4 голосов
/ 21 марта 2012

Может быть, я что-то упустил, но это должно сделать это:

SELECT a, 
       count(*) as cnt,
       array_agg(b) as all_values
FROM your_table
GROUP BY a
3 голосов
/ 21 марта 2012

Это то, что вам нужно:

SELECT A, COUNT(*), array_agg(b)
FROM YourTable
GROUP BY A
...