Чи можу я об'єднати кілька рядків MySQL в одне поле?


1214

Використовуючи MySQL, я можу зробити щось на кшталт:

SELECT hobbies FROM peoples_hobbies WHERE person_id = 5;

Мій вихід:

shopping
fishing
coding

але замість цього я просто хочу 1 ряд, 1 стовпчик:

Очікуваний вихід:

shopping, fishing, coding

Причина полягає в тому, що я вибираю декілька значень з декількох таблиць, і після всіх об'єднань у мене набагато більше рядків, ніж я хотів би.

Я шукав функцію в MySQL Doc, і вона не схожа на CONCATабо CONCAT_WSфункції приймають набори результатів.

Так хтось тут знає, як це зробити?


9
Я лише написав невеличку демонстрацію про те, як використовувати group_concat, який може бути корисним для вас: giombetti.com/2013/06/06/mysql-group_concat
Marc Giombetti

Відповіді:


1737

Ви можете використовувати GROUP_CONCAT:

SELECT person_id, GROUP_CONCAT(hobbies SEPARATOR ', ')
FROM peoples_hobbies
GROUP BY person_id;

Як заявив Людвіг у своєму коментарі, ви можете додати DISTINCTоператора, щоб уникнути дублікатів:

SELECT person_id, GROUP_CONCAT(DISTINCT hobbies SEPARATOR ', ')
FROM peoples_hobbies 
GROUP BY person_id;

Як заявив Ян у своєму коментарі, ви також можете сортувати значення, перш ніж застосовувати їх, використовуючи ORDER BY:

SELECT person_id, GROUP_CONCAT(hobbies ORDER BY hobbies ASC SEPARATOR ', ')
FROM peoples_hobbies
GROUP BY person_id;

Як заявив Даг у своєму коментарі, в результаті є обмеження на 1024 байти. Щоб вирішити цю проблему, запустіть цей запит перед запитом:

SET group_concat_max_len = 2048;

Звичайно, ви можете змінити 2048відповідно до своїх потреб. Для обчислення та призначення значення:

SET group_concat_max_len = CAST(
    (SELECT SUM(LENGTH(hobbies)) + COUNT(*) * LENGTH(', ')
    FROM peoples_hobbies 
    GROUP BY person_id)
    AS UNSIGNED
);

154
Просто пам’ятайте про обмеження 1024 байтів у отриманому стовпці (див. Параметр group_concat_max_len )
даг,

81
І додавши DISTINCTпараметр, ви не отримаєте жодного подвоєння. ... GROUP_CONCAT(DISTINCT hobbies)
Людвіг

3
Моєю потребою було отримати ВСІ дані з одного стовпця. Не використовуйте пункт GROUP BY для цього. Приклад: SELECT GROUP_CONCAT (електронні листи SEPARATOR ',') від користувачів;
Джонатан Бержерон

1
Дякую, я не знав, що існує обмеження довжини групи. Мені це було потрібно, щоб обійти створений мною список монстрів.
Патрік

9
Якщо ви хочете відсортувати хобі в результаті інтегрувалися використання рядка:SELECT person_id, GROUP_CONCAT(hobbies ORDER BY hobbies ASC SEPARATOR ', ') FROM peoples_hobbies GROUP BY person_id
Jan

106

Погляньте, GROUP_CONCATчи підтримує ваша версія MySQL (4.1). Детальнішу інформацію див. У документації .

Це виглядатиме приблизно так:

  SELECT GROUP_CONCAT(hobbies SEPARATOR ', ') 
  FROM peoples_hobbies 
  WHERE person_id = 5 
  GROUP BY 'all';

11
Я думаю, що group by 'all'це не потрібно (до того ж небажано), оскільки це призначається всім рядкам рядків, allа потім порівнюється рядки між цими рядками. Чи правий я?
Кшисиек

74

Чергуйте синтаксис для об'єднання декількох окремих рядків

Попередження: Ця публікація зробить вас голодними.

Подано:

Мені здалося, що я хочу вибрати кілька окремих рядків - замість групи - і об'єднатись у певне поле.

Скажімо, у вас є таблиця ідентифікаторів продуктів та їх назв та цін:

+------------+--------------------+-------+
| product_id | name               | price |
+------------+--------------------+-------+
|         13 | Double Double      |     5 |
|         14 | Neapolitan Shake   |     2 |
|         15 | Animal Style Fries |     3 |
|         16 | Root Beer          |     2 |
|         17 | Lame T-Shirt       |    15 |
+------------+--------------------+-------+

Тоді у вас є якийсь фантазійний аякс, який відображає цих цуценят як прапорці.

Ваш голодний гіпоподібний користувач вибирає 13, 15, 16. Жодного десерту для неї сьогодні ...

Знайти:

Спосіб узагальнення замовлення вашого користувача в одному рядку, з чистою mysql.

Рішення:

Використовуйте GROUP_CONCATз в INстатті :

mysql> SELECT GROUP_CONCAT(name SEPARATOR ' + ') AS order_summary FROM product WHERE product_id IN (13, 15, 16);

Які виходи:

+------------------------------------------------+
| order_summary                                  |
+------------------------------------------------+
| Double Double + Animal Style Fries + Root Beer |
+------------------------------------------------+

Бонусне рішення:

Якщо ви також хочете загальну ціну, киньте SUM():

mysql> SELECT GROUP_CONCAT(name SEPARATOR ' + ') AS order_summary, SUM(price) AS total FROM product WHERE product_id IN (13, 15, 16);
+------------------------------------------------+-------+
| order_summary                                  | total |
+------------------------------------------------+-------+
| Double Double + Animal Style Fries + Root Beer |    10 |
+------------------------------------------------+-------+

PS: Вибачте, якщо у вас немає входу -виходу поблизу ...


11
Незважаючи на те, що це хороша відповідь, це звучить більше як реклама, ніж чисто відповідь. Все-таки хороша добре сформована відповідь.
FliiFe

1
Можу чи я отримати допомогу stackoverflow.com/q/60278898/11697039 @elbowlobstercowstand
ZUS



25

У моєму випадку у мене був рядок Ідентифікаторів, і його потрібно було передати в char, інакше результат був закодований у двійковий формат:

SELECT CAST(GROUP_CONCAT(field SEPARATOR ',') AS CHAR) FROM table

1
Дякую! Без CASTмене [BLOB - 14 Bytes]в результаті були значення LIKE !
Mel_T

1
Можу чи я отримати допомогу stackoverflow.com/q/60278898/11697039 @Fedir Рихтік
ZUS

16

Використовуйте MySQL (5.6.13) змінної сесії та оператора присвоєння, як описано нижче

SELECT @logmsg := CONCAT_ws(',',@logmsg,items) FROM temp_SplitFields a;

тоді ти можеш дістати

test1,test11

2
це швидше, ніж GROUP_CONCAT?
jave.web

1
Я перевірив це під PHPMyAdmin з сервером MySQL v5.6.17 на опис стовпця (VARCHAR (50)) в тестовій таблиці , але вона повертає поле BLOB для кожного запису:SELECT @logmsg := CONCAT_ws(',',@logmsg,description) from test
Jan

14

У мене був складніший запит, і я виявив, що мені потрібно використовувати GROUP_CONCATзовнішній запит, щоб змусити його працювати:

Оригінальний запит:

SELECT DISTINCT userID 
FROM event GROUP BY userID 
HAVING count(distinct(cohort))=2);

Вкладено:

SELECT GROUP_CONCAT(sub.userID SEPARATOR ', ') 
FROM (SELECT DISTINCT userID FROM event 
GROUP BY userID HAVING count(distinct(cohort))=2) as sub;

Сподіваюся, це може комусь допомогти.


9

Хтось шукає тут, як користуватися GROUP_CONCATпідзапитом - розміщуючи цей приклад

SELECT i.*,
(SELECT GROUP_CONCAT(userid) FROM favourites f WHERE f.itemid = i.id) AS idlist
FROM items i
WHERE i.id = $someid

Тому GROUP_CONCATтреба використовувати всередині підзапиту, не загортаючи його.


1
Це було саме те , що я шукав
Бумеранг

7

Спробуйте це:

DECLARE @Hobbies NVARCHAR(200) = ' '

SELECT @Hobbies = @Hobbies + hobbies + ',' FROM peoples_hobbies WHERE person_id = 5;

2
Ось що я отримав: "Нерозпізнаний тип заяви. (біля "ОГЛЯД" у позиції 0) "
Істіаке Ахмед

1

у нас є два способи об'єднати стовпці в MySql

select concat(hobbies) as `Hobbies` from people_hobbies where 1

Або

select group_concat(hobbies) as `Hobbies` from people_hobbies where 1
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.