What I have
I have multiple tables with a primary key key and a value. Each key might be present in all tables or only in a subset of tables.
Here are example tables:
Tab1:
| key | value |
|---|---|
| A | 1 |
| C | 3 |
Tab2:
| key | value |
|---|---|
| A | 10 |
| D | 10 |
Tab3:
| key | value |
|---|---|
| B | 20 |
| D | 10 |
What I want
I want to join the tables in such a fashion, that I get one row for each existing key and one column for each table. If a key is not present in one of the tables, null should be assumed. So for the example above I'd like to get this result:
| key | tab1 | tab2 | tab3 |
|---|---|---|---|
| A | 1 | 10 | NULL |
| B | NULL | NULL | 20 |
| C | 3 | NULL | NULL |
| D | NULL | 10 | 10 |
What I have tried so far
Here is what I came up with, which works:
with tab1 as (
select * from (values('A', 1), ('C', 3))x(key, value)
),
tab2 as (
select * from (values('A', 10), ('D', 10))x(key, value)
),
tab3 as (
select * from (values('B', 20), ('D', 10))x(key, value)
)
select
coalesce(tab1.key, tab2.key, tab3.key) "key",
tab1.value tab1,
tab2.value tab2,
tab3.value tab3
from tab1
full outer join tab2 on tab2.key = tab1.key
full outer join tab3 on tab3.key = coalesce(tab1.key, tab2.key)
order by coalesce(tab1.key, tab2.key, tab3.key)
The question
In the case above my query looks still quite OK, however in the real case I need to join 6 tables and the key is actually distributed across three columns. This leads to very long join statements. The statement for the sixth table looks like this:
full outer join tab6
on tab6.key1 = coalesce(tab1.key1, tab2.key1, tab3.key1, tab4.key1, tab5.key1)
and tab6.key2 = coalesce(tab1.key2, tab2.key2, tab3.key2, tab4.key2, tab5.key2)
and tab6.key3 = coalesce(tab1.key3, tab2.key3, tab3.key3, tab4.key3, tab5.key3)
The explosion of copy&pasted coalesce-calls is somewhat disturbing from a code quality perspective.
Is there another, simpler way to get the result I want?