24

Given a table defined as such:

CREATE TABLE test_values(name TEXT, values INTEGER[]);

...and the following values:

| name  | values  |
+-------+---------+
| hello | {1,2,3} |
| world | {4,5,6} |

I'm trying to find a query which will return:

| name  | value |
+-------+-------+
| hello | 1     |
| hello | 2     |
| hello | 3     |
| world | 4     |
| world | 5     |
| world | 6     |

I've reviewed the upstream documentation on accessing arrays, and tried to think about what a solution using the unnest() function would look like, but have been coming up empty.

An ideal solution would be easy to use even in cases where there were a significant number of columns other than the array being expanded and no primary key. Handling a case with more than one array is not important.

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441

2 Answers2

30

We can put the set-returning function unnest() into the SELECT list like Raphaël suggests. This used to exhibit corner case problems before Postgres 10. See:

Since Postgres 9.3 we can also use a LATERAL join for this. It is the cleaner, standard-compliant way to put set-returning functions into the FROM list, not into the SELECT list:

SELECT name, value
FROM   tbl, unnest(values) value;  -- implicit CROSS JOIN LATERAL

One subtle difference: this drops rows with empty / NULL values from the result since unnest() returns no row, while the same is converted to a NULL value in the FROM list and returned anyway. The 100 % equivalent query is:

SELECT t.name, v.value
FROM   tbl t
LEFT   JOIN unnest(t.values) v(value) ON true;

See:

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
  • Thank you for the nice answer. A quick question. What is the `v(value)` on the last query. I understood that `v` is the alias, but I have never seen this notation in the past. Many thanks again for your answer – George Pipis Sep 20 '21 at 09:46
13

Well, you give the data, the doc, so... let's mix it ;)

select 
 name, 
 unnest(values) as value 
from test_values

see SqlFiddle

Raphaël Althaus
  • 59,727
  • 6
  • 96
  • 122
  • Unfamiliar with the semantics of selecting a tuple with a sequence as one of its elements, I can plead. I'll accept this when the timer runs out. – Charles Duffy Aug 13 '15 at 20:26