Как использовать GROUP_CONCAT в CONCAT в MySQL


117

Если у меня есть таблица со следующими данными в MySQL:

id       Name       Value
1          A          4
1          A          5
1          B          8
2          C          9

как мне преобразовать его в следующий формат?

id         Column
1          A:4,5,B:8
2          C:9


Думаю, надо использовать GROUP_CONCAT. Но я не знаю, как это работает.

Ответы:


160
select id, group_concat(`Name` separator ',') as `ColumnName`
from
(
  select 
    id, 
    concat(`Name`, ':', group_concat(`Value` separator ',')) as `Name`
  from mytbl
  group by 
    id, 
    `Name`
) tbl
group by id;

Вы можете увидеть это здесь: Sql Fiddle Demo . Именно то, что вам нужно.

Обновление разбиения в два этапа. Сначала мы получаем таблицу, в которой все значения (разделенные запятыми) соответствуют уникальному [Имя, идентификатор]. Затем из полученной таблицы мы получаем все имена и значения как одно значение для каждого уникального идентификатора. См. Это объяснено здесь. SQL Fiddle Demo (прокрутите вниз, так как он имеет два набора результатов)

Изменить Произошла ошибка при чтении вопроса, я сгруппировал его только по идентификатору. Но два group_contacts необходимы, если (значения должны быть объединены, сгруппированы по имени и идентификатору, а затем по всем идентификаторам). Предыдущий ответ был

select 
id,group_concat(concat(`name`,':',`value`) separator ',')
as Result from mytbl group by id

Вы можете увидеть, как это реализовано здесь: SQL Fiddle Demo


Это не соответствует тому, о чем просил Бисва.
eisberg

3
Я считаю важным предупредить людей о том, что использование только одного типа сепаратора может быть невыгодным. Я предлагаю сделать разделитель «имя» точкой с запятой (;), а разделитель значений может оставаться запятой (,)
Фанди Сусанто

4
Также обратите внимание, что это GROUP_CONCATможет без уведомления усечь его вывод до group_concat_max_len. SET group_concat_max_len=...поможет, но в любом случае рекомендуется проверить, что возвращаемая длина (в байтах?) меньше, чем group_concat_max_len.
Tuomassalo 05

2
Также обратите внимание, что group_concat встречает одно значение NULL, оно опускает всю строку, содержащую его. Я работаю вокруг этого во втором предостережения здесь .
MatrixManAtYrService

1
Если кто-то столкнулся с проблемой со ссылкой на SQL Fiddle, указанной в ответе. Рабочая Fiddle здесь: sqlfiddle.com/#!9/42f994/601/0
Hitesh

21

Пытаться:

CREATE TABLE test (
  ID INTEGER,
  NAME VARCHAR (50),
  VALUE INTEGER
);

INSERT INTO test VALUES (1, 'A', 4);
INSERT INTO test VALUES (1, 'A', 5);
INSERT INTO test VALUES (1, 'B', 8);
INSERT INTO test VALUES (2, 'C', 9);

SELECT ID, GROUP_CONCAT(NAME ORDER BY NAME ASC SEPARATOR ',')
FROM (
  SELECT ID, CONCAT(NAME, ':', GROUP_CONCAT(VALUE ORDER BY VALUE ASC SEPARATOR ',')) AS NAME
  FROM test
  GROUP BY ID, NAME
) AS A
GROUP BY ID;

SQL Fiddle: http://sqlfiddle.com/#!2/b5abe/9/0


2
Да, Айсберг +1. Ваш ответ довольно точный и более ранний. Я ошибся в своем первом ответе
Сами

9
SELECT ID, GROUP_CONCAT(CONCAT_WS(':', NAME, VALUE) SEPARATOR ',') AS Result 
FROM test GROUP BY ID

7
Было бы неплохо, если бы вы могли описать свой ответ. Это предложение улучшить этот и будущие ответы. Спасибо!
Луис Крус,

5

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

SELECT id,GROUP_CONCAT(name, ':', value SEPARATOR "|") FROM sample GROUP BY id

Вы получаете быстрые и правильные результаты, и вы можете разделить результат на СЕПАРАТОР "|". Я всегда использую этот разделитель, потому что его невозможно найти внутри строки, поэтому он уникален. Нет проблем с двумя буквами «А», вы определяете только значение. Или вы можете сделать еще один столбец с буквой, что еще лучше. Как это :

SELECT id,GROUP_CONCAT(DISTINCT(name)), GROUP_CONCAT(value SEPARATOR "|") FROM sample GROUP BY name

2
 SELECT id, GROUP_CONCAT(CONCAT_WS(':', Name, CAST(Value AS CHAR(7))) SEPARATOR ',') AS result 
    FROM test GROUP BY id

вы должны использовать приведение или преобразование, иначе будет возвращен BLOB

результат

id         Column
1          A:4,A:5,B:8
2          C:9

вам нужно снова обработать результат с помощью такой программы, как python или java


0

IF OBJECT_ID('master..test') is not null Drop table test

CREATE TABLE test (ID INTEGER, NAME VARCHAR (50), VALUE INTEGER );
INSERT INTO test VALUES (1, 'A', 4);
INSERT INTO test VALUES (1, 'A', 5);
INSERT INTO test VALUES (1, 'B', 8);
INSERT INTO test VALUES (2, 'C', 9);

select distinct NAME , LIST = Replace(Replace(Stuff((select ',', +Value from test where name = _a.name for xml path('')), 1,1,''),'<Value>', ''),'</Value>','') from test _a order by 1 desc

Имя моей таблицы - test, а для объединения я использую синтаксис For XML Path (''). Функция stuff вставляет строку в другую строку. Он удаляет указанную длину символов в первой строке в начальной позиции, а затем вставляет вторую строку в первую строку в начальной позиции.

Функции STUFF выглядят так: STUFF (символьное_выражение, начало, длина, символьное_выражение)

character_expression - это выражение символьных данных. character_expression может быть константой, переменной или столбцом символьных или двоичных данных.

start Целочисленное значение, указывающее местоположение для начала удаления и вставки. Если начало или длина отрицательны, возвращается пустая строка. Если start длиннее первого character_expression, возвращается пустая строка. start может иметь тип bigint.

длина Целое число, указывающее количество удаляемых символов. Если длина больше, чем первое character_expression, удаление происходит до последнего символа в последнем character_expression. длина может иметь тип bigint.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.