trick in the bag: case inside group_concat to return nulls
Posted in database on September 22nd, 2011 by adminThe group_concat function in MySQL aggregates results into comma separated values. It ignores null values. In other words, if your result set has 10 rows and you’re using group_concat against one of the columns in a query, and one of your results for the column is null, you will get 9 instead of 10 results.
I had a java programmer using group_concat on some columns in a multi-row query to make the query 1 row, so that comma separated values of each column are returned in a single-row result set.
Java guys do this a lot to construct “maps” of data. The problem is (as stated above), if I use group_concat, and one of the values is null, group_concat will return n-1 values. If I’m making a map, and one of the columns in my map has too few columns, my map is no longer usable. Values don’t line up. Let me explain what I am talking about.
Take this example:
mysql> select * from test_concat;
+----+-------+----------+
| id | color | shape |
+----+-------+----------+
| 1 | blue | square |
| 2 | green | triangle |
| 3 | NULL | rhombus |
| 4 | red | circle |
+----+-------+----------+
4 rows in set (0.00 sec)
I’ve got three columns. The color column has one null value, corresponding to the ID 3 and the shape “rhombus”. Now, let’s group_concat these columns.
mysql> select group_concat(id) ids, group_concat(color) colors, group_concat(shape) shapes from test_concat;
+---------+----------------+--------------------------------+
| ids | colors | shapes |
+---------+----------------+--------------------------------+
| 1,2,3,4 | blue,green,red | square,triangle,rhombus,circle |
+---------+----------------+--------------------------------+
1 row in set (0.00 sec)
As you can see, group_concat has eliminated the null in the color column. If I tried to map this data set in a program, I would come up with (1, blue, square), (2, green, triangle) — so far so good right… (3, red, rhombus) – now wait a sec. Rhombus had a null color in the real data set. Now the circle will end up with no color. This is wrong.
The “colors” result set does not have enough values in the map. group_concat has removed the null, so these values don’t “line up” correctly.
Well – embedding a little case statement inside your group_concat will solve this problem.
In the previous statement, what if I replaced:
group_concat(color) colors
with:
group_concat((case when color is null then 'null' else color end)) as colors
Here is the modified statement and result set.
mysql> select group_concat(id) ids, group_concat((case when color is null then 'null' else color end)) colors, group_concat(shape) shapes from test_concat;
+---------+---------------------+--------------------------------+
| ids | colors | shapes |
+---------+---------------------+--------------------------------+
| 1,2,3,4 | blue,green,null,red | square,triangle,rhombus,circle |
+---------+---------------------+--------------------------------+
1 row in set (0.00 sec)
Voila. Now we have enough values in each column and the map stays intact.
Just another trick in the bag.

