MariaDB GROUP_CONCAT()

MariaDB has a GROUP_CONCAT() function that enables us to return columns from a query as a delimited list.

Syntax

The syntax goes like this:

GROUP_CONCAT([DISTINCT] expr [,expr ...]
             [ORDER BY {unsigned_integer | col_name | expr}
                 [ASC | DESC] [,col_name ...]]
             [SEPARATOR str_val]
             [LIMIT {[offset,] row_count | row_count OFFSET offset}])

Example

Suppose we run the following query:

SELECT PetName 
FROM Pets;

And we get the following result:

+---------+
| PetName |
+---------+
| Fluffy  |
| Fetch   |
| Scratch |
| Wag     |
| Tweet   |
| Fluffy  |
| Bark    |
| Meow    |
+---------+
8 rows in set (0.001 sec)

We can use GROUP_CONCAT() to return all of those rows as a delimited list.

To achieve this, all we need to do is pass the PetName column as an argument to the GROUP_CONCAT() function:

SELECT GROUP_CONCAT(PetName) 
FROM Pets;

Result:

+-------------------------------------------------+
| GROUP_CONCAT(PetName)                           |
+-------------------------------------------------+
| Fluffy,Fetch,Scratch,Wag,Tweet,Fluffy,Bark,Meow |
+-------------------------------------------------+
1 row in set (0.003 sec)

Ordering

We can use the ORDER BY clause to order the output of this function:

SELECT GROUP_CONCAT(PetName ORDER BY PetName DESC)
FROM Pets;

Result:

Wag,Tweet,Scratch,Meow,Fluffy,Fluffy,Fetch,Bark

Note that this only sorts the output of the GROUP_CONCAT() function – it’s completely independent of any ordering applied to the SELECT statement itself.

Limiting the Output

We can use the LIMIT clause to limit how many items are included in the list:

SELECT GROUP_CONCAT(PetName LIMIT 3)
FROM Pets;

Result:

Fluffy,Fetch,Scratch

Any ordering is applied before the LIMIT clause:

SELECT GROUP_CONCAT(PetName ORDER BY PetName DESC LIMIT 3)
FROM Pets;

Result:

Wag,Tweet,Scratch

Note that the LIMIT clause is only supported from MariaDB 10.3.3.

The DISTINCT Clause

We can use the DISTINCT clause to return unique values. In other words, if there are duplicate values, only one occurrence is returned:

SELECT GROUP_CONCAT(DISTINCT PetName ORDER BY PetName ASC)
FROM Pets;

Result:

Bark,Fetch,Fluffy,Meow,Scratch,Tweet,Wag

In this case, Fluffy only appears once. When we run it without the DISTINCT clause, Fluffy appears twice.

Changing the Separator

By default, the list uses the comma as the delimiter. But we can change this if we like:

SELECT GROUP_CONCAT(PetName SEPARATOR '-')
FROM Pets;

Result:

Fluffy-Fetch-Scratch-Wag-Tweet-Fluffy-Bark-Meow

We can even use an empty string to remove all separators (so that the values are concatenated):

SELECT GROUP_CONCAT(PetName SEPARATOR '')
FROM Pets;

And we get the following result:

FluffyFetchScratchWagTweetFluffyBarkMeow

Grouped Query Results

We can include GROUP_CONCAT() in a query with a GROUP BY clause to achieve a result like this:

SELECT 
    PetTypeId,
    GROUP_CONCAT(PetName ORDER BY PetName ASC)
FROM Pets
GROUP BY PetTypeId
ORDER BY PetTypeId;

Result:

+-----------+--------------------------------------------+
| PetTypeId | GROUP_CONCAT(PetName ORDER BY PetName ASC) |
+-----------+--------------------------------------------+
|         1 | Tweet                                      |
|         2 | Fluffy,Meow,Scratch                        |
|         3 | Bark,Fetch,Fluffy,Wag                      |
+-----------+--------------------------------------------+

In my database, the actual pet type names are in another table called PetTypes. We could therefore run an INNER JOIN on the PetTypes table to get the actual pet type names:

SELECT 
    pt.PetType,
    GROUP_CONCAT(p.PetName ORDER BY p.PetName ASC)
FROM Pets p
INNER JOIN PetTypes pt ON
p.PetTypeId = pt.PetTypeId
GROUP BY pt.PetType
ORDER BY pt.PetType ASC;

Result:

+---------+------------------------------------------------+
| PetType | GROUP_CONCAT(p.PetName ORDER BY p.PetName ASC) |
+---------+------------------------------------------------+
| Bird    | Tweet                                          |
| Cat     | Fluffy,Meow,Scratch                            |
| Dog     | Bark,Fetch,Fluffy,Wag                          |
+---------+------------------------------------------------+

Length Limitations

The maximum returned length in bytes is determined by the group_concat_max_len server system variable, which defaults to 1M (in MariaDB 10.2.4 and higher) or 1K (in MariaDB 10.2.3 and lower). If group_concat_max_len is 512 or lower, the return type is VARBINARY or VARCHAR; otherwise, the return type is BLOB or TEXT. The choice between binary or non-binary types depends from the input.

You can check the current value like this:

SHOW VARIABLES LIKE '%group_concat%';

The syntax for changing this value goes as follows:

SET [GLOBAL | SESSION] group_concat_max_len = val;

Where val is an unsigned integer.