Concatenating column values in PostgreSQL with string_agg

February 22, 2018

PostgreSQL is an amazing database, no surprises here. But every now and then I discover an amazing little feature that I was missing, this week was the time to discover string_agg.

Suppose that you have two tables course and student and want to list every student enrolled in a given discipline.

Usually I did this with a quick Python script by grouping the course and than using than making a simple ', '.join(). With the aggregate string_agg function I now do it directly in the query.

The string_agg is very similar to the join method in Python, from the PG docs:

Input values concatenated into a string, separated by delimiter

The function have the following signature: string_agg(expression, delimiter)

I’ve prepared a simple fiddle to show this, ignore the weird tables. :)

If you wish you can jump directly to it here.

Our course table:

| id |             name |
|----|------------------|
|  1 |      Mathematics |
|  2 |          English |
|  3 |       Portuguese |
|  4 | Computer Science |

And our student table, which have a FK to course:

| id |   name | course |
|----|--------|--------|
|  1 |    Joe |      1 |
|  2 |    Ana |      1 |
|  3 | Amanda |      4 |
|  4 |  Jacob |      3 |
|  5 |  Maria |      3 |
|  6 | Joanne |      1 |

Let’s run a simple query joining them together:

SELECT
    c.name AS "course",
    s.name AS "student"
FROM course c
    JOIN student s ON c.id = s.course
ORDER BY 1;

We now have this:

|           course | student |
|------------------|---------|
| Computer Science |  Amanda |
|      Mathematics |     Joe |
|      Mathematics |     Ana |
|      Mathematics |  Joanne |
|       Portuguese |   Jacob |
|       Portuguese |   Maria |

Now, editing this query to make it concatenate the students by course is very easy, changes are bold:

SELECT
    c.name AS "course",
    string_agg(s.name, ', ') AS "students"
FROM course c
    JOIN student s ON c.id = s.course
GROUP BY 1
ORDER BY 1;

And now this is our result:

|           course |         students |
|------------------|------------------|
| Computer Science |           Amanda |
|      Mathematics | Joe, Ana, Joanne |
|       Portuguese |     Jacob, Maria |

And if you are using Django the ORM supports it as well! Just take a look at the docs.

Cool, eh? :)