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