我有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
我该如何做到这一点?
答案 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