我如何 select Left Join 中的每一行只有一行
How do I select Just one row for each row in a Left Join
所以我有两个表:Customers
和 Calls
。
这些 table 之间存在 one to many
关系。 即一个客户可以有多个电话
我正在尝试创建一个左连接,以便我有一个输出,其中列出了 Customers
只有一次 和最近的 CallDate
来自Calls
table.
使用这张图:
我构建了以下 SQL
语句:
Select Customers.*, Calls.CallDate
From Customers
Left Join Calls
on Customers.Id=Calls.CustomerId
但这给了我一个单独的 Customer
行,每个 Call
如何根据最近的 CallDate
为每个 Customer
获得 一行 行?
您可以使用ROW_NUMBER
window函数:
Select Customers.*, c.CallDate
From Customers
Left Join (
SELECT CustomerId, CallDate,
ROW_NUMBER() OVER (PARTITION BY CustomerId
ORDER BY CallDate DESC) AS rn
FROM Calls
) AS c on Customers.Id = c.CustomerId AND c.rn = 1
ROW_NUMBER
和 PARTITION BY
子句枚举 CustomerId
分区内的记录。由于 ORDER BY CallDate DESC
子句,编号 1 分配给具有最大 CallDate
值的记录。
一个简单的方法是使用 Outer Apply
:
Select c.*, ca.*
From Customers c outer apply
(select top 1 ca.*
from Calls ca
where c.id = ca.CustomerId
order by CallDate desc
) ca;
但是,如果您只想要最近的通话日期,则聚合是典型的方法。一种方法:
select c.*, max_callDate
from customers c left join
(select CustomerId, max(CallDate) as max_callDate
from calls
group by CustomerId
) ca
on c.id = ca.CustomerId;
您可以使用外部应用
Select Customers.*, Calls.CallDate
From Customers
outer apply (select top 1 * from Calls c where Customers.Id=c.CustomerId order by c.CallDate desc ) as Calls
由于您永远只想要 一个 结果,因此您可以使用 CROSS APPLY
:
进行编码
Select Customers.*, c.CallDate
From Customers
CROSS APPLY (SELECT TOP 1 * Calls
WHERE Customers.Id=Calls.CustomerId ORDER BY CallDate DESC) c
如果您希望某些客户没有来电 (OUTER JOIN
),您可以使用 OUTER APPLY
而不是 CROSS APPLY
。
所以我有两个表:Customers
和 Calls
。
这些 table 之间存在 one to many
关系。 即一个客户可以有多个电话
我正在尝试创建一个左连接,以便我有一个输出,其中列出了 Customers
只有一次 和最近的 CallDate
来自Calls
table.
使用这张图:
我构建了以下 SQL
语句:
Select Customers.*, Calls.CallDate
From Customers
Left Join Calls
on Customers.Id=Calls.CustomerId
但这给了我一个单独的 Customer
行,每个 Call
如何根据最近的 CallDate
为每个 Customer
获得 一行 行?
您可以使用ROW_NUMBER
window函数:
Select Customers.*, c.CallDate
From Customers
Left Join (
SELECT CustomerId, CallDate,
ROW_NUMBER() OVER (PARTITION BY CustomerId
ORDER BY CallDate DESC) AS rn
FROM Calls
) AS c on Customers.Id = c.CustomerId AND c.rn = 1
ROW_NUMBER
和 PARTITION BY
子句枚举 CustomerId
分区内的记录。由于 ORDER BY CallDate DESC
子句,编号 1 分配给具有最大 CallDate
值的记录。
一个简单的方法是使用 Outer Apply
:
Select c.*, ca.*
From Customers c outer apply
(select top 1 ca.*
from Calls ca
where c.id = ca.CustomerId
order by CallDate desc
) ca;
但是,如果您只想要最近的通话日期,则聚合是典型的方法。一种方法:
select c.*, max_callDate
from customers c left join
(select CustomerId, max(CallDate) as max_callDate
from calls
group by CustomerId
) ca
on c.id = ca.CustomerId;
您可以使用外部应用
Select Customers.*, Calls.CallDate
From Customers
outer apply (select top 1 * from Calls c where Customers.Id=c.CustomerId order by c.CallDate desc ) as Calls
由于您永远只想要 一个 结果,因此您可以使用 CROSS APPLY
:
Select Customers.*, c.CallDate
From Customers
CROSS APPLY (SELECT TOP 1 * Calls
WHERE Customers.Id=Calls.CustomerId ORDER BY CallDate DESC) c
如果您希望某些客户没有来电 (OUTER JOIN
),您可以使用 OUTER APPLY
而不是 CROSS APPLY
。