2010-04-01 4 views
169

У меня есть таблица, и я бы хотел потянуть одну строку на id с значениями полей, которые были объединены.Postgresql GROUP_CONCAT эквивалент?

В моей таблице, к примеру, у меня есть это:

TM67 | 4 | 32556 
TM67 | 9 | 98200 
TM67 | 72 | 22300 
TM99 | 2 | 23009 
TM99 | 3 | 11200 

И я хотел бы вывод:

TM67 | 4,9,72 | 32556,98200,22300 
TM99 | 2,3 | 23009,11200 

В MySQL я был в состоянии использовать агрегатную функцию GROUP_CONCAT, но что, похоже, не работает здесь ... Есть ли эквивалент для PostgreSQL или другой способ сделать это?

+0

Не ответ, но проверить http://www.postgresonline.com/journal/index.php? /archives/14-CrossTab-Queries-in-PostgreSQL-using-tablefunc-contrib.html. – Kuberchaun

+1

http://stackoverflow.com/questions/1943433/postgresql-concat-ws-like-function –

+0

Возможный дубликат [Имитация группы \ _concat MySQL-функция в SQL Server?] (Http://stackoverflow.com/questions/451415/simulating-group-concat-mysql-function-in-sql-server) – ntalbs

ответ

155

Это, вероятно, является хорошей отправной точкой (версия 8.4+ только):

SELECT id_field, array_agg(value_field1), array_agg(value_field2) 
FROM data_table 
GROUP BY id_field 

array_agg возвращает массив, но вы можете CAST, что текст и редактировать при необходимости (см пояснения ниже).

До версии 8.4, вы должны определить сами перед использованием:

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

(переоформленную из документации PostgreSQL)

Разъяснения:

  • Результат литья массив в текст - это то, что результирующая строка начинается и заканчивается фигурными фигурными скобками. Эти скобки необходимо удалить каким-либо способом, если они не желательны.
  • Кастинг ANYARRAY to TEXT лучше всего имитирует вывод CSV, поскольку элементы, содержащие встроенные запятые, имеют двойные кавычки на выходе в стандартном стиле CSV. Ни array_to_string(), ни string_agg() (добавленная функция «group_concat» в 9.1) не цитируют строки со встроенными запятыми, что приводит к некорректному количеству элементов в результирующем списке.
  • Новая функция 9.1 string_agg() НЕ передает первые результаты в ТЕКСТ. Поэтому «string_agg (value_field)» генерирует ошибку, если value_field является целым числом. «string_agg (value_field :: text)» потребуется. Метод array_agg() требует только одного приведения после агрегации (а не приведения за значение).
+0

И в 9.0 вы будете иметь listagg() –

+4

Чтобы получить CSV запрос должен быть: ВЫБЕРИТЕ id_field, array_to_string (array_agg (value_field1), ' '), array_to_string (array_agg (value_field2),',') ОТ data_table GROUP BY id_field – Nux

+2

Здесь вы не можете использовать array_to_string. Если ваше значение_поля содержит встроенную запятую, результирующий CSV неверен. Использование array_agg() и литье в TEXT правильно цитирует строки со встроенными запятыми. Единственное предостережение состоит в том, что он также включает в себя начальные и конечные фигурные скобки, поэтому мое утверждение «и отредактируйте по мере необходимости». Я отредактирую, чтобы уточнить этот момент. –

30
SELECT array_to_string(array(SELECT a FROM b),', '); 

будет делать также.

+4

Этот файл также работает до 9.0 - проверял его с помощью 8.4. 5 – chrpes

+0

Отличный !!! Работает на меня. Teste также Postgres 8.3.6. Танки! – vandersondf

+0

Можно ли что-то сделать в [этом комментарии] (http://stackoverflow.com/questions/2560946/postgresql-group-concat-equivalent#comment23843695_8803563), где вы агрегируете в определенном порядке? Как бы вы обрабатывали группировку по одному столбцу и упорядочивали другим (например, чтобы объединить переменные в продольном наборе данных)? –

178

Since 9.0 это еще проще:

SELECT id, 
     string_agg(some_column, ',') 
FROM the_table 
GROUP BY id 
+18

Обратите внимание, что синтаксис также позволяет указать порядок значений в строке (или массиве, используя 'array_agg'), например. 'string_agg (some_column, ',' ORDER BY some_column)' или даже 'string_agg (фамилия || ',' || forename, ';' ORDER BY surname, forename)' – IMSoP

+0

@a_horse_with_no_name Я вижу так много ваших замечательных сообщений в SO, пока я работаю над различными проблемами Postgres. Я не вижу способа связаться с вами в вашем профиле. Вы открыты для общения/работы над проектами за пределами SO? Извиняюсь за то, что вы пинговали вас через комментарий, если нет. Если вы открыты для возможного сотрудничества/работы вне SO, вы можете связаться со мной из моего профиля, если это так: http://stackoverflow.com/users/2565593/steve-midgley - Вы делаете замечательную работу здесь - спасибо ! (И редакторам я полагаюсь на мета-комментарии, подобные этому, чтобы оставить комментарий: http://meta.stackexchange.com/a/58715/278168) –

8

Попробуйте так:

select field1, array_to_string(array_agg(field2), ',') 
from table1 
group by field1; 
Смежные вопросы