В MySQL можете да върнете резултатите от заявката си като списък, разделен със запетая, като използвате GROUP_CONCAT()
функция.
GROUP_CONCAT()
функцията е създадена специално с цел обединяване на резултата от заявка в списък, разделен със запетая или разделител по ваш избор.
Тази статия предоставя примери за това как работи всичко.
Данните
Първо, нека използваме следните данни в първите няколко примера:
USE Solutions; SELECT TaskName FROM Tasks;
Резултат:
+-------------------+ | TaskName | +-------------------+ | Do garden | | Feed cats | | Paint roof | | Take dog for walk | | Relax | | Feed cats | +-------------------+
Основен пример
Ето основен пример за демонстрация на GROUP_CONCAT()
функция:
SELECT GROUP_CONCAT(TaskName) FROM Tasks;
Резултат:
+------------------------------------------------------------------+ | GROUP_CONCAT(TaskName) | +------------------------------------------------------------------+ | Do garden,Feed cats,Paint roof,Take dog for walk,Relax,Feed cats | +------------------------------------------------------------------+
Както можете да видите, всеки ред от набора от резултати е конкатениран в един ред. По подразбиране списъкът е разделен със запетая.
Имайте предвид, че има ограничения за това колко дълъг може да бъде този списък. Повече за това по-късно в статията.
Пример – РАЗЛИЧЕН
Можете да използвате DISTINCT
за премахване на дубликати (така че дублираните записи да станат един запис).
Пример:
SELECT GROUP_CONCAT(DISTINCT TaskName) FROM Tasks;
Резултат:
+--------------------------------------------------------+ | GROUP_CONCAT(DISTINCT TaskName) | +--------------------------------------------------------+ | Do garden,Feed cats,Paint roof,Relax,Take dog for walk | +--------------------------------------------------------+
Така че в този случай „Хранене на котки“ е посочено само веднъж, докато в предишния пример беше посочено два пъти.
Пример – ORDER BY
Можете да използвате ORDER BY
за да подредите резултатите по дадена колона.
Пример:
SELECT GROUP_CONCAT(DISTINCT TaskName ORDER BY TaskName DESC) FROM Tasks;
Резултат:
+--------------------------------------------------------+ | GROUP_CONCAT(DISTINCT TaskName ORDER BY TaskName DESC) | +--------------------------------------------------------+ | Take dog for walk,Relax,Paint roof,Feed cats,Do garden | +--------------------------------------------------------+
Така че в този случай използвам DESC
за да уточните, че трябва да бъде в низходящ ред. Алтернативната (и по подразбиране) стойност е ASC
за изкачване.
Пример – Посочете разделител
По подразбиране списъкът е разделен със запетая. Въпреки това, можете да посочите разделител по ваш избор, ако е необходимо.
За да направите това, използвайте SEPARATOR
последвано от стойността на низовия литерал, която трябва да се вмъкне между стойностите на групата.
Пример:
SELECT GROUP_CONCAT(DISTINCT TaskName SEPARATOR ' + ') FROM Tasks;
Резултат:
+----------------------------------------------------------------+ | GROUP_CONCAT(DISTINCT TaskName SEPARATOR ' + ') | +----------------------------------------------------------------+ | Do garden + Feed cats + Paint roof + Relax + Take dog for walk | +----------------------------------------------------------------+
Пример – Комбиниране на колони
Можете също да конкатенирате колони и да предоставите техен разделител, като предоставите стойност на низов литерал.
Пример:
SELECT GROUP_CONCAT(TaskId, ') ', TaskName SEPARATOR ' ') FROM Tasks;
Резултат:
+------------------------------------------------------------------------------------+ | GROUP_CONCAT(TaskId, ') ', TaskName SEPARATOR ' ') | +------------------------------------------------------------------------------------+ | 1) Do garden 2) Feed cats 3) Paint roof 4) Take dog for walk 5) Relax 6) Feed cats | +------------------------------------------------------------------------------------+
В този пример връщаме и двата TaskId
колона и TaskName
колона, разделена със затварящи скоби и интервал. Ние също така използваме SEPARATOR
аргумент, за да посочите, че разделителят, който ще се използва между всеки (свързан) ред, трябва да бъде интервал (вместо запетая по подразбиране).
Групирани резултати
GROUP_CONCAT()
функцията може да бъде полезна за случаи, когато искате да предоставите списък с резултати, групирани по друга колона.
Например, може да искате списък с изпълнители, като всеки изпълнител е последван от списък с албумите, които са издали.
За да демонстрирате това, да кажем, че имаме база данни с две таблици; Artists
и Albums
. Между тези таблици има връзка едно към много. За всеки изпълнител може да има много албуми.
Така че обикновената заявка, свързваща двете таблици, може да изглежда така:
USE Music; SELECT ar.ArtistName, al.AlbumName FROM Artists ar INNER JOIN Albums al ON ar.ArtistId = al.ArtistId;
Резултат:
+------------------------+--------------------------+ | ArtistName | AlbumName | +------------------------+--------------------------+ | Iron Maiden | Powerslave | | AC/DC | Powerage | | Jim Reeves | Singing Down the Lane | | Devin Townsend | Ziltoid the Omniscient | | Devin Townsend | Casualties of Cool | | Devin Townsend | Epicloud | | Iron Maiden | Somewhere in Time | | Iron Maiden | Piece of Mind | | Iron Maiden | Killers | | Iron Maiden | No Prayer for the Dying | | The Script | No Sound Without Silence | | Buddy Rich | Big Swing Face | | Michael Learns to Rock | Blue Night | | Michael Learns to Rock | Eternity | | Michael Learns to Rock | Scandinavia | | Tom Jones | Long Lost Suitcase | | Tom Jones | Praise and Blame | | Tom Jones | Along Came Jones | | Allan Holdsworth | All Night Wrong | | Allan Holdsworth | The Sixteen Men of Tain | +------------------------+--------------------------+
Както можете да видите, когато използвате този формат, ако изпълнител има повече от един албум, този изпълнител е посочен няколко пъти – по веднъж за всеки албум.
Бихме могли да променим тази заявка, така че всеки изпълнител да бъде посочен само веднъж. Ако изпълнител има повече от един албум, всички албуми се показват в едно поле в списък, разделен със запетая. Можем да направим това благодарение на GROUP_CONCAT()
функция.
Пример:
USE Music; SELECT ar.ArtistName, GROUP_CONCAT(al.AlbumName) FROM Artists ar INNER JOIN Albums al ON ar.ArtistId = al.ArtistId GROUP BY ArtistName;
Резултат:
+------------------------+----------------------------------------------------------------------------+ | ArtistName | GROUP_CONCAT(al.AlbumName) | +------------------------+----------------------------------------------------------------------------+ | AC/DC | Powerage | | Allan Holdsworth | All Night Wrong,The Sixteen Men of Tain | | Buddy Rich | Big Swing Face | | Devin Townsend | Epicloud,Ziltoid the Omniscient,Casualties of Cool | | Iron Maiden | Somewhere in Time,Piece of Mind,Powerslave,Killers,No Prayer for the Dying | | Jim Reeves | Singing Down the Lane | | Michael Learns to Rock | Eternity,Scandinavia,Blue Night | | The Script | No Sound Without Silence | | Tom Jones | Long Lost Suitcase,Praise and Blame,Along Came Jones | +------------------------+----------------------------------------------------------------------------+
Внимавайте с дължината!
Едно важно нещо, което трябва да знаете, когато използвате GROUP_CONCAT()
е, че резултатът се съкращава до максималната дължина, предоставена от group_concat_max_len
системна променлива, която има стойност по подразбиране 1024
.
Стойността на тази променлива може да бъде зададена по-висока, като се използва следния синтаксис:
SET [GLOBAL | SESSION] group_concat_max_len = val;
Където val
е цяло число без знак.
Обърнете внимание обаче, че ефективната максимална дължина на връщаната стойност сама по себе си е ограничена от стойността на max_allowed_packet
.