如何为左连接中的每一行选择一行

时间:2016-02-22 12:24:38

标签: sql sql-server left-join

所以我有两个表:CustomersCalls

这些表之间存在one to many关系。 即。一位客户可以拨打多个电话

我正在尝试创建一个左连接,以便我有一个输出,Customers列出一次CallDate来自Calls } table。

使用此图表:

enter image description here

我构建了以下SQL语句:

Select Customers.*, Calls.CallDate 
From Customers 
Left Join Calls 
on Customers.Id=Calls.CustomerId

但是这为每个Customer

提供了一个单独的Call

如何基于最新的Customer为每个CallDate获取一行行?

4 个答案:

答案 0 :(得分:3)

一种简单的方法是使用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;

答案 1 :(得分:1)

您可以使用ROW_NUMBER窗口功能:

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个分区内的记录。由于CallDate子句,数字1被分配给具有最大ORDER BY CallDate DESC值的记录。

答案 2 :(得分:1)

您可以使用外部申请

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

答案 3 :(得分:1)

由于您只需要一个结果,您可以使用 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