SQL: Full outer join or Union or neither?

主宰稳场 提交于 2021-01-29 13:12:07

问题


I have an A_to_C table which is many-to-many join table between A and C

╔═══════╦══════════╗
║ a_col ║  c_col   ║
╠═══════╬══════════╣
║ a     ║ x        ║
║ b     ║ y        ║
║ c     ║ z        ║
╚═══════╩══════════╝

I also have a B_to_C table which is many-to-many join table from B and C

╔═══════╦═══════╗
║ b_col ║ c_col ║
╠═══════╬═══════╣
║ g     ║ u     ║
║ h     ║ v     ║
║ i     ║ w     ║
╚═══════╩═══════╝

I want to achieve a result like this:

╔═══════╦═══════╦═══════╗
║ a_col ║ c_col ║ b_col ║
╠═══════╬═══════╬═══════╣
║ a     ║ x     ║ NULL  ║
║ b     ║ y     ║ NULL  ║
║ c     ║ z     ║ NULL  ║
║ NULL  ║ u     ║ g     ║
║ NULL  ║ v     ║ h     ║
║ NULL  ║ w     ║ i     ║
╚═══════╩═══════╩═══════╝

I have no idea if I can use joins because x, y, z values in A_to_C cannot be matched with u, v, w values in B_to_C

I can't use unions because I need separate a_col and b_col columns or can I?

I might not be aware of a SQL construct that can achieve the desired result though.

As a bonus, I wanna transform the columns in the results as:

╔═══════╦═══════╦════════╗
║ a_col ║ c_col ║ b_col  ║
╠═══════╬═══════╬════════╣
║ true  ║ x     ║ false  ║
║ true  ║ y     ║ false  ║
║ true  ║ z     ║ false  ║
║ false ║ u     ║ true   ║
║ false ║ v     ║ true   ║
║ false ║ w     ║ true   ║
╚═══════╩═══════╩════════╝

TIA!


回答1:


You can use UNION ALL:

select a_col, c_col, null b_col
from A_to_C
union all
select null, c_col, b_col
from B_to_C

and for the other query:

select 
  (t.a_col is not null) a_col, 
  t.c_col, 
  (t.b_col is not null) b_col
from (
  select a_col, c_col, null b_col
  from A_to_C
  union all
  select null, c_col, b_col
  from B_to_C
) t

Or set the boolean values directly in th eunioned queries:

select true a_col, c_col, false b_col
from A_to_C
union all
select false a_col, c_col, true b_col
from B_to_C

See the demo.
Results:

> a_col | c_col | b_col
> :---- | :---- | :----
> a     | x     | null 
> b     | y     | null 
> c     | z     | null 
> null  | u     | g    
> null  | v     | h    
> null  | w     | i 

and

> a_col | c_col | b_col
> :---- | :---- | :----
> t     | x     | f    
> t     | y     | f    
> t     | z     | f    
> f     | u     | t    
> f     | v     | t    
> f     | w     | t 



回答2:


I think you can use LEFT OUTER JOINs for this.

SELECT a.a_col, c.c_col, b.b_col
FROM C c
LEFT OUTER JOIN A_to_C a ON c.c_col = a.c_col
LEFT OUTER JOIN B_to_C b ON c.c_col = b.c_col
WHERE a.a_col IS NOT NULL OR b.b_col IS NOT NULL;

The WHERE clause is optional if you can guarantee that all values in c have a corresponding value in a or b or both.

For the bonus query, change the SELECT to

SELECT a.a_col IS NOT NULL AS a_col,
    c.c_col,
    b.b_col IS NOT NULL AS b_col

Here's the db fiddle.

Btw, depending on what your use-case is, if a value in c can be in BOTH a and b, using JOINs will give you a single row for that value of c, while using UNION ALL will give you two rows, one with NULL in a and one with NULL in b. I don't know which is more performant for large tables.



来源:https://stackoverflow.com/questions/61147861/sql-full-outer-join-or-union-or-neither

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!