SQL Left JOINING 3表

时间:2016-08-24 19:30:27

标签: sql oracle join max left-join

我有1张表:

Contacts (ID integer, Name text, ATT_ID integer)

我的表格中填充了以下值:

(1, 'Alice', 1)
(2, 'Bob', 1)
(3, 'Carol', 1)
(4, 'Dave', 4)
(5, 'Eve', 4)
(6, 'Frank', 6)

目标是使用配对的ATT_ID加入这些联系人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

我该如何做到这一点?

1 个答案:

答案 0 :(得分:0)

假设您的RDBMS支持窗口函数...

这可以通过为每个子组生成行号并仅显示最小行号来实现。

这也假设每组中不超过3个。

以下是ORACLE特定的,但应该与MS SQL和Postgresql和DB2一起使用。它不适用于MySQL,因为不支持窗口函数。

请注意with block as built仅适用于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 

enter image description here