0

Given a table Names:

name_id|naam|
-------+----+
      1|Ad  |
      2|Bo  |
      3|Che |

and a table Widgets where each widget has an array of name id's:

widget_id|name_ids|
---------+--------+
        1|{1,2,3} |
        2|{3,2}   |

I need to create a SELECT query to replace an array with name_ids with an array of names like this:

widget_id|names      |
---------+-----------+
        1|{Ad,Bo,Che}|
        2|{Che,Bo}   |

In this SO post I found how to connect names to name ID's, but this leads to a new widget row for each name:

select * from 
(select widget_id , unnest (name_ids) name_id from widgets w ) ww
inner join names n on ww.name_id = n.name_id
widget_id|name_id|name_id|naam|
---------+-------+-------+----+
        1|      1|      1|Ad  |
        1|      2|      2|Bo  |
        1|      3|      3|Che |
        2|      3|      3|Che |
        2|      2|      2|Bo  |

What is missing, and cannot find, is some sort of GROUP BY WIDGET_ID and an inverse function of UNNEST, in order to put all names of a widget into a names array, but there seems no function NEST. I was experienced in Oracle, but PostgreSQL seems more advanced, and complex.

Any help is appreciated.

2
  • 1
    This would be so much easier with a properly normalized model (which would also allow you to define proper foreign keys) Commented Sep 21, 2022 at 14:41
  • @a_horse_with_no_name so true, but someone invents an array type and then people are storing all kinds of data as array . . . Commented Sep 21, 2022 at 17:27

1 Answer 1

2

You need to group by the widget_id after "normalizing" the widgets on the fly

select w.widget_id, w.name_ids, array_agg(n.naam) names
from widgets w
  cross join unnest(name_ids) as u(name_id)
  join names n on n.name_id = u.name_id
group by w.widget_id, w.name_ids
order by w.widget_id;

Output:

widget_id|name_ids|names      |
---------+--------+-----------+
        1|{1,2,3} |{Ad,Bo,Che}|
        2|{3,2}   |{Che,Bo}   |
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.