I'd like to convert single rows into multiple rows in PostgreSQL, where some of the columns are removed. Here's an example of the current output:
name | st | ot | dt |
-----|----|----|----|
Fred | 8 | 2 | 3 |
Jane | 8 | 1 | 0 |
Samm | 8 | 0 | 6 |
Alex | 8 | 0 | 0 |
Using the following query:
SELECT
name, st, ot, dt
FROM
times;
And here's what I want:
name | t | val |
-----|----|-----|
Fred | st | 8 |
Fred | ot | 2 |
Fred | dt | 3 |
Jane | st | 8 |
Jane | ot | 1 |
Samm | st | 8 |
Samm | dt | 6 |
Alex | st | 8 |
How can I modify the query to get the above desired output?
The core problem is the reverse of a pivot / crosstab operation. Sometimes called "unpivot".
Basically, Abelisto's query is the way to go in Postgres 9.3 or later. Related:
You may want to use
LEFT JOIN LATERAL ... ON u.val <> 0
to include names without valid values in the result (and shorten the syntax a bit).If you have more than a few value columns (or varying lists of columns) you may want to use a function to build and execute the query automatically:
Call:
Or:
Columns names are provided as string literals and must be in correct (case-sensitive!) spelling with no extra double-quotes. See:
dbfiddle here
Related with more examples and explanation:
One way: