Могу ли я объединить несколько строк MySQL в одно поле? - PullRequest
1085 голосов
/ 10 ноября 2008

Используя MySQL, я могу сделать что-то вроде:

SELECT hobbies FROM peoples_hobbies WHERE person_id = 5;

Мой вывод:

shopping
fishing
coding

но вместо этого я просто хочу 1 строку, 1 столбец:

Ожидаемый результат:

shopping, fishing, coding

Причина в том, что я выбираю несколько значений из нескольких таблиц, и после всех объединений у меня гораздо больше строк, чем хотелось бы.

Я искал функцию в MySQL Doc , и не похоже, что функции CONCAT или CONCAT_WS принимают наборы результатов, так что кто-нибудь здесь знает, как это сделать?

Ответы [ 11 ]

1566 голосов
/ 10 ноября 2008

Вы можете использовать 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
);
94 голосов
/ 10 ноября 2008

Посмотрите на GROUP_CONCAT, если ваша версия MySQL (4.1) поддерживает это. Подробнее см. в документации .

Это будет выглядеть примерно так:

  SELECT GROUP_CONCAT(hobbies SEPARATOR ', ') 
  FROM peoples_hobbies 
  WHERE person_id = 5 
  GROUP BY 'all';
63 голосов
/ 24 сентября 2014

Альтернативный синтаксис для объединения несколько отдельных строк

ВНИМАНИЕ: этот пост сделает вас голодным.

Дано:

Я обнаружил, что хочу выбрать несколько отдельных строк - вместо группы - и объединить в определенном поле.

Допустим, у вас есть таблица идентификаторов продуктов, их названий и цен:

+------------+--------------------+-------+
| 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 поблизости ...

35 голосов
/ 08 апреля 2010

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

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

25 голосов
/ 10 ноября 2008

Есть функция агрегирования GROUP, GROUP_CONCAT .

22 голосов
/ 10 июня 2014

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

SELECT CAST(GROUP_CONCAT(field SEPARATOR ',') AS CHAR) FROM table
14 голосов
/ 27 сентября 2013

Используйте переменную сеанса MySQL (5.6.13) и оператор присваивания, как показано ниже

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

тогда вы можете получить

test1,test11
12 голосов
/ 29 апреля 2015

У меня был более сложный запрос, и я обнаружил, что мне нужно использовать 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;

Надеюсь, это кому-нибудь поможет.

7 голосов
/ 26 февраля 2015

Попробуйте это:

DECLARE @Hobbies NVARCHAR(200) = ' '

SELECT @Hobbies = @Hobbies + hobbies + ',' FROM peoples_hobbies WHERE person_id = 5;
1 голос
/ 26 апреля 2019

Для тех, кто ищет здесь, как использовать 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 необходимо использовать внутри подзапроса, а не оборачивать его.

...