我如何 select Left Join 中的每一行只有一行

How do I select Just one row for each row in a Left Join

所以我有两个表:CustomersCalls

这些 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_NUMBERPARTITION 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