Як використовувати 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 (прокрутіть униз, оскільки у нього є два набори результатів)

Редагувати При читанні запитання сталася помилка, я згрупував лише id. Але два групи_контакту потрібні, якщо (Значення мають бути об'єднані, згруповані за Іменем та ідентифікатором, а потім над усіма за ідентифікатором). Попередня відповідь була

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

Ви можете бачити його реалізованим тут: SQL Fiddle Demo


Це не дає того, про що просив Бісва.
eisberg

3
Я думаю, що важливо попередити людей, що використання лише одного виду сепараторів може бути невигідним. Я пропоную зробити роздільник "ім'я" як крапку з комою (;), а роздільник значень може залишитися як кома (,)
Fandi Susanto

4
Будь ласка, зверніть увагу, що GROUP_CONCATможе мовчки усікати свій результат group_concat_max_len. SET group_concat_max_len=...допоможе, але все-таки гарна ідея перевірити, що повернута (байт?) довжина менше group_concat_max_len.
tuomassalo

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

Ви отримуєте швидкі та правильні результати, і ви можете розділити результат за цим SEPARATOR "|". Я завжди використовую цей роздільник, тому що його неможливо знайти всередині рядка, тому він унікальний. Немає проблем із двома A, ви визначаєте лише значення. Або ви можете мати ще один колон, з буквою, що ще краще. Подобається це :

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

ви повинні використовувати cast або конвертувати, інакше повернеться 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

Назва моєї таблиці - тест, і для конкретизації я використовую синтаксис For XML Path (''). Функція речі вставляє рядок в інший рядок. Він видаляє вказану довжину символів у першому рядку в початковому положенні, а потім вставляє другий рядок у перший рядок у початковому положенні.

Функції STUFF виглядають так: STUFF (вираз_вираз, початок, довжина, вираз символів)

символ_вираз - це вираження даних символів. символ_експресія може бути постійною, змінною або стовпчиком або символу, або двійкових даних.

start - ціле значення, яке визначає місце для початку видалення та вставки. Якщо початок або довжина від’ємні, повертається нульовий рядок. Якщо запуск довший, ніж перший символьний вираз, повертається нульовий рядок. старт може бути типу bigint.

length - ціле число, яке визначає кількість символів, які потрібно видалити. Якщо довжина більша, ніж перший вираз символу, вилучення відбувається до останнього символу в останньому виразі_ символу. довжина може бути типу bigint.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.