问题
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