SQL 左 JOINING 3 表
SQL Left JOINING 3 Tables
我有1个Table:
Contacts (ID integer, Name text, ATT_ID integer)
我的 Table 填充了这些值:
(1, 'Alice', 1)
(2, 'Bob', 1)
(3, 'Carol', 1)
(4, 'Dave', 4)
(5, 'Eve', 4)
(6, 'Frank', 6)
目标是将这些联系人 ID 与配对的 ATT_ID 连接起来。
这是我当前的SQL-代码:
SELECT t1.ID as ID, t1.Name , tt.Name , tt2.Name
FROM Contacts as t1
LEFT JOIN (
SELECT MIN(t2.ID), t2.Name, t2.ATT_ID FROM Contacts as t2
WHERE t2.ID <> t2.ATT_ID)
AS tt ON t1.ID = tt.ATT_ID
LEFT JOIN (
SELECT MAX(t3.ID), t3.Name, t3.ATT_ID FROM Contacts as t3
WHERE t3.ID <> t3.ATT_ID)
AS tt2 ON t1.ID = tt2.ATT_ID
WHERE t1.ID = t1.ATT_ID;
我的结果是:
Alice | Bob | null
Dave | null | Eve
Frank | null | null
但是想要的结果应该是这样的:
Alice | Bob | Carol
Dave | Eve | null
Frank | null | null
我怎样才能做到这一点?
假设您的 RDBMS 支持 Window 函数...
这可以通过为每个子组生成一个行号并只显示最小的行号来实现。
这还假设您在每组中的人数不超过 3 人。
以下是特定于 ORACLE 的,但应该适用于 MS SQL 和 Postgresql 以及 DB2。它不适用于 MySQL,因为 window 函数不受支持。
请注意,构建的 with 块仅适用于 ORACLE。
With contacts (ID, Name, ATT_ID) as (
Select 1, 'Alice', 1 from dual union all
Select 2, 'Bob', 1 from dual union all
Select 3, 'Carol', 1 from dual union all
Select 4, 'Dave', 4 from dual union all
Select 5, 'Eve', 4 from dual union all
Select 6, 'Frank', 6 from dual)
--FROM HERE ON should work if window functions supported.
Select * from (
Select T1.Name N1, T2.Name N2, T3.Name N3, Row_Number() Over (partition by T1.ATT_ID order by T1.ID) rn
FROM Contacts T1
LEFT JOIN Contacts T2
on T1.ATT_ID = T2.ATT_ID
and T1.ID < T2.ID
LEFT JOIN contacts T3
on T2.ATT_ID = T3.ATT_ID
and T2.ID < T3.ID
and T1.ID < T3.ID) B
WHERE RN =1
我有1个Table:
Contacts (ID integer, Name text, ATT_ID integer)
我的 Table 填充了这些值:
(1, 'Alice', 1)
(2, 'Bob', 1)
(3, 'Carol', 1)
(4, 'Dave', 4)
(5, 'Eve', 4)
(6, 'Frank', 6)
目标是将这些联系人 ID 与配对的 ATT_ID 连接起来。
这是我当前的SQL-代码:
SELECT t1.ID as ID, t1.Name , tt.Name , tt2.Name
FROM Contacts as t1
LEFT JOIN (
SELECT MIN(t2.ID), t2.Name, t2.ATT_ID FROM Contacts as t2
WHERE t2.ID <> t2.ATT_ID)
AS tt ON t1.ID = tt.ATT_ID
LEFT JOIN (
SELECT MAX(t3.ID), t3.Name, t3.ATT_ID FROM Contacts as t3
WHERE t3.ID <> t3.ATT_ID)
AS tt2 ON t1.ID = tt2.ATT_ID
WHERE t1.ID = t1.ATT_ID;
我的结果是:
Alice | Bob | null
Dave | null | Eve
Frank | null | null
但是想要的结果应该是这样的:
Alice | Bob | Carol
Dave | Eve | null
Frank | null | null
我怎样才能做到这一点?
假设您的 RDBMS 支持 Window 函数...
这可以通过为每个子组生成一个行号并只显示最小的行号来实现。
这还假设您在每组中的人数不超过 3 人。
以下是特定于 ORACLE 的,但应该适用于 MS SQL 和 Postgresql 以及 DB2。它不适用于 MySQL,因为 window 函数不受支持。
请注意,构建的 with 块仅适用于 ORACLE。
With contacts (ID, Name, ATT_ID) as (
Select 1, 'Alice', 1 from dual union all
Select 2, 'Bob', 1 from dual union all
Select 3, 'Carol', 1 from dual union all
Select 4, 'Dave', 4 from dual union all
Select 5, 'Eve', 4 from dual union all
Select 6, 'Frank', 6 from dual)
--FROM HERE ON should work if window functions supported.
Select * from (
Select T1.Name N1, T2.Name N2, T3.Name N3, Row_Number() Over (partition by T1.ATT_ID order by T1.ID) rn
FROM Contacts T1
LEFT JOIN Contacts T2
on T1.ATT_ID = T2.ATT_ID
and T1.ID < T2.ID
LEFT JOIN contacts T3
on T2.ATT_ID = T3.ATT_ID
and T2.ID < T3.ID
and T1.ID < T3.ID) B
WHERE RN =1