Czy Mogę połączyć wiele wierszy MySQL w jedno pole?

Używając MySQL, mogę zrobić coś takiego:

SELECT hobbies FROM peoples_hobbies WHERE person_id = 5;

Moje Wyjście:

shopping
fishing
coding

Ale zamiast tego chcę tylko 1 rząd, 1 kol:

Oczekiwany Wynik:

shopping, fishing, coding

Powodem jest to, że wybieram wiele wartości z wielu tabel, a po wszystkich połączeniach mam o wiele więcej wierszy, niż bym chciał.

Szukałem funkcji na MySQL Doc i nie wygląda na to, że funkcje CONCAT lub CONCAT_WS akceptują zestawy wyników, więc czy ktoś tutaj wie jak to zrobić?

Author: DineshDB, 2008-11-10

9 answers

Możesz użyć GROUP_CONCAT:

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

Jak stwierdził Ludwig w swoim komentarzu, możesz dodać operator DISTINCT, aby uniknąć duplikatów:

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

Jak powiedział Jan w ich komentarzu, można również sortować wartości przed implodowaniem za pomocą ORDER BY:

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

Jak stwierdził Dag w swoim komentarzu,istnieje limit 1024 bajtów na wynik. Aby rozwiązać ten problem, uruchom to zapytanie przed zapytaniem:

SET group_concat_max_len = 2048

Oczywiście możesz zmienić 2048 według twoje potrzeby. Aby obliczyć i przypisać wartość:

SET group_concat_max_len = CAST(
    (SELECT SUM(LENGTH(hobbies)) + COUNT(*) * LENGTH(', ')
    FROM peoples_hobbies GROUP BY person_id)
    AS UNSIGNED
)
 1424
Author: che,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-08 15:48:13

Spójrz na GROUP_CONCAT Czy Twoja wersja MySQL (4.1) ją obsługuje. Zobacz Dokumentacja Aby uzyskać więcej szczegółów.

Wyglądałoby to tak:

  SELECT GROUP_CONCAT(hobbies SEPARATOR ', ') 
  FROM peoples_hobbies 
  WHERE person_id = 5 
  GROUP BY 'all';
 81
Author: lpfavreau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-01 08:13:19

Składnia alternatywna do konkatenacji wiele, pojedyncze wiersze

uwaga: ten post sprawi, że będziesz głodny.

Podane:

Stwierdziłem, że chciałem wybrać wiele, pojedynczych wierszy -zamiast grupy-i połączyć na określonym polu.

Załóżmy, że masz tabelę identyfikatorów produktów, ich nazw i cen:

+------------+--------------------+-------+
| 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 |
+------------+--------------------+-------+

Potem masz jakiś fantazyjny AJAX, który wymienia te szczeniaki jako pola wyboru.

Twój użytkownik hungry-hippo wybiera 13, 15, 16. Nie ma dziś deseru...

Znaleźć:

Sposób na podsumowanie kolejności użytkownika w jednej linii, z czystym mysql.

Rozwiązanie:

Użyj GROUP_CONCATz klauzuli IN :

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

Które wyjście:

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

Rozwiązanie Bonusowe:

Jeśli chcesz również cenę całkowitą, Wrzuć 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: przepraszam, jeśli nie masz In-N-Out w pobliżu...

 54
Author: elbowlobstercowstand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-07 17:39:54

Można zmienić maksymalną długość wartości GROUP_CONCAT, ustawiając parametr group_concat_max_len.

Zobacz szczegóły w MySQL documentation.

 34
Author: pau.moreno,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-27 14:25:08

Istnieje funkcja agregująca grupy, GROUP_CONCAT .

 24
Author: Dean Rather,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-27 23:03:11

W moim przypadku miałem rząd Idów i trzeba było wrzucić go do char, w przeciwnym razie wynik został zakodowany do formatu binarnego:

SELECT CAST(GROUP_CONCAT(field SEPARATOR ',') AS CHAR) FROM table
 19
Author: Fedir RYKHTIK,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-10 09:24:31

Użyj zmiennej sesji MySQL(5.6.13) i operatora przypisania, jak poniżej

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

Wtedy możesz dostać

test1,test11
 13
Author: Shen liang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-27 18:47:25

Miałem bardziej skomplikowane zapytanie i stwierdziłem, że muszę użyć GROUP_CONCAT w zewnętrznym zapytaniu, aby to zadziałało:

Oryginalne Zapytanie:

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

Imploded:

SELECT GROUP_CONCAT(sub.userID SEPARATOR ', ') 
FROM (SELECT DISTINCT userID FROM event 
GROUP BY userID HAVING count(distinct(cohort))=2) as sub;
Mam nadzieję, że to komuś pomoże.
 10
Author: Alex Bowyer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-29 16:35:34

Spróbuj tego:

DECLARE @Hobbies NVARCHAR(200) = ' '

SELECT @Hobbies = @Hobbies + hobbies + ',' FROM peoples_hobbies WHERE person_id = 5;
 6
Author: thejustv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-18 03:37:56