加入第二个表中的最后一个记录,但包含第二个表中没有匹配的记录

时间:2014-02-06 18:55:58

标签: sql sql-server join

我知道有很多类似的问题。实际上我使用this并且它有效,但我无法弄清楚如何包含第二个表中没有匹配的记录。

我在MS SQL Server上使用示例Northwind数据库。

使用此查询:

SELECT Customers.CustomerID, Customers.CompanyName, Orders.OrderID, Orders.OrderDate
FROM Customers
LEFT OUTER JOIN Orders
ON Customers.CustomerID=Orders.CustomerID
INNER JOIN
    (
        SELECT CustomerID, MAX(OrderDate) maxDate
        FROM Orders
        GROUP BY CustomerID
    ) b ON Orders.CustomerID = b.CustomerID AND
            Orders.OrderDate = b.maxDate
ORDER BY Orders.OrderDate 

我得到了正确的结果,但缺少了与之不匹配的记录。

如果我使用LEFT OUTER JOIN而不是INNER JOIN:

SELECT Customers.CustomerID, Customers.CompanyName, Orders.OrderID, Orders.OrderDate
FROM Customers
LEFT OUTER JOIN Orders
ON Customers.CustomerID=Orders.CustomerID
LEFT OUTER JOIN
    (
        SELECT CustomerID, MAX(OrderDate) maxDate
        FROM Orders
        GROUP BY CustomerID
    ) b ON Orders.CustomerID = b.CustomerID AND
            Orders.OrderDate = b.maxDate
ORDER BY Orders.OrderDate 

我得到了丢失的记录,但在这种情况下,我重复了客户名称。

我想:获得只有最后一个订单的客户名单,如果他没有订单,他的名字应该存在。

3 个答案:

答案 0 :(得分:2)

您有重复的客户名称,因为您链接了orderdate。因此,如果您在某个客户的最后日期有两个或更多订单,您将获得所有这些最后订单。 如果我假设orderid与orderdate具有相同的序列,则以下语句应该只为每个客户返回一行。

select cs.*, o.* from customers cs
left outer join (
  select customerid, max(orderid) as orderid from orders
  group by customerid
) lnk on cs.customerid = lnk.customerid
left outer join orders o on lnk.orderid = o.orderid
order by cs.customerid

答案 1 :(得分:1)

执行此操作的最佳方法是CTE ROW_NUMBER()此查询的成本会更高,因为您只需按Orders一次而不是两次获取数据,一次获得最大记录。

WITH    LastOrder
          AS ( SELECT CustomerID
                   ,OrderID
                   ,OrderDate
                   ,ROW_NUMBER() OVER ( PARTITION BY CustomerID ORDER BY OrderDate DESC ) AS RowNum
                FROM Orders)
    SELECT c.CustomerID
           ,c.CompanyName
           ,lo.OrderID
           ,lo.OrderDate
        FROM Customers AS c
        LEFT OUTER JOIN LastOrder AS lo
            ON c.Customer_id = lo.CustomerID
               AND lo.RowNum = 1

答案 2 :(得分:0)

我使用此answer来解决此问题。

参见代码:

select Customers.CustomerID, Customers.CompanyName, Orders.OrderID, Orders.OrderDate
 from Customers
left outer join  Orders ON Customers.CustomerID=Orders.CustomerID
where   Orders.OrderDate is null OR
       Orders.OrderDate = 
       ( SELECT MAX(OrderDate)
           FROM Orders
          WHERE Customers.CustomerID=Orders.CustomerID)       
ORDER BY Customers.CustomerID 

它完全符合我的要求。

更新:最好使用OrderID而不是OrderTime:

select Customers.CustomerID, Customers.CompanyName, Orders.OrderID, Orders.OrderDate
 from Customers
left outer join  Orders ON Customers.CustomerID=Orders.CustomerID
where   Orders.OrderID is null OR
       Orders.OrderID = 
       ( SELECT MAX(OrderID)
           FROM Orders
          WHERE Customers.CustomerID=Orders.CustomerID)       
ORDER BY Customers.CustomerID