Могу ли я объединить несколько строк 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
Марк Джомбетти

Ответы:

1739

Вы можете использовать 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
);
че
источник
155
Просто помните об ограничении 1024 байта в результирующем столбце (см. Параметр group_concat_max_len )
Dag
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';
lpfavreau
источник
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: Извиняюсь, если у вас нет In-N-Out поблизости ...

elbowlobstercowstand
источник
11
Несмотря на то, что это хороший ответ, это больше похоже на рекламу, чем просто ответ. Все еще хороший, хорошо сформированный ответ.
FliiFe
1
Могу ли я получить помощь stackoverflow.com/q/60278898/11697039 @elbowlobstercowstand
zus
39

Вы можете изменить максимальную длину GROUP_CONCATзначения, установив group_concat_max_lenпараметр.

Подробности смотрите в документации MySQL .

pau.moreno
источник
25

В моем случае у меня был ряд идентификаторов, и было необходимо привести его к типу char, в противном случае результат был закодирован в двоичном формате:

SELECT CAST(GROUP_CONCAT(field SEPARATOR ',') AS CHAR) FROM table
Федир РЫХТИК
источник
1
Спасибо! Без CASTменя были значения, как [BLOB - 14 Bytes]в результате!
Mel_T
1
Могу ли я получить помощь stackoverflow.com/q/60278898/11697039 @Fedir RYKHTIK
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;
thejustv
источник
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
Raghavendra
источник