2017-05-03 109 views
2

入门手册:我已经浏览了堆栈溢出的几个示例,许多让我接近我需要的东西,但并不完全符合我的需要。请裸露,并且我发现无用的一件事是很多答案都抛出了解决方案,而没有解释它如何工作以及为什么需要零件。因此,如果答案可以包含对该查询的解释和分解,那将是很棒的。谢谢。SQL Server最大的每组查询:最新日期的客户信息

问题:我有一个客户表,如下所示。

Id  Name  Account  Active 
1  Bob  ABC   True 
2  Jenny BED   True 
3  Tony  POT   False 
4  David DON   False 

我也有订单表。见下面

OrderId  CustomerId  OrderDate  Status 
1   2    2016-04-01 3 
2   2    2016-09-05 7 
3   2    2017-02-20 5 
4   3    2015-02-20 8 
5   4    2017-04-16 3 

我需要什么。所以我需要它具有Customer.Id表,Customer.Name,Customer.Account,Customer.Active,Order.Status并且具有最新的订购日期状态为3或7. 该表应显示Order.Status和LatestDate的所有客户和空值,其中客户从未订购或订单不符合状态条件。见下面的例子。

CustomerId  Name  Account  Active  Status  LatestDate 
1    Bob  ABC   True  NULL  NULL 
2    Jenny BED   True  7   2016-09-05 
3    Tony  POT   False  NULL  NULL 
4    David DON   False  3   2017-04-16 

因此,大家可以看到Bob和托尼都有空的状态和latestDate因为他们要么没有做出交易或不符合现状的标准订单为3或7。大卫只有一个订单,所以他的最新工作很简单。珍妮有多个订单和多个符合条件的订单,所以它将订单与最新日期相加,并将其添加到我们的表格(仍然考虑状态是3还是7)。

现在在这个问题的以前的尝试,我已经结束了所有交易帐户(不只是3和7),我有重复的客户显示(由于日期不同,不能使用不同的客户),而在另一次尝试中,它获得了所有的数据,但忽略了任何有空值的东西。如前所述,我已经看到了堆栈溢出的大量示例,但它们似乎都给我的案例带来了问题或问题,并且没有提供足够的解释或故障让我能够根据我的原因对其进行修改。

所以如果有人可以提供解决方案以及SQL的细分,只是为了我的清楚理解(以及其他人)。提前致谢。

我最新的尝试是:

Select Distinct c.Id, c.[Name], c.Account, c.Active, o.Status, 
LatestDates.LatestDate 
From Customer as c 
Left Outer Join 
(Select CustomerId, Max(OrderDate) LatestDate From [Order] Group By 
CustomerId) LatestDates On c.Id = LatestDates.CustomerId 
Left Join [Order] o on LatestDates.CustomerId = o.CustomerId and 
LatestDates.LatestDate = o.OrderDate 
Where c.Active is not null 
Order by c.Active 

但是这种解决方案并没有考虑到3,7检查,我不明白这足以证实我得到的数据是正确的。这是来自不同的堆栈溢出问题。让我知道你是否需要更多细节。

回答

0

使用top with tiesrow_number()

select top 1 with ties 
    c.Id, c.[Name], c.Account, c.Active, o.Status, o.OrderDate 
from Customer as c 
    left join [Order] o 
    on c.Id= o.CustomerId 
    and o.Status in (3,7) 
where c.Active is not null 
order by row_number() over (partition by c.Id order by o.OrderDate desc) 

outer apply()

select 
    c.Id, c.[Name], c.Account, c.Active, o.Status, o.OrderDate 
from Customer as c 
    outer apply (
    select top 1 
     i.Status, i.OrderDate 
    from [Order] i 
    where i.CustomerId = c.Id 
     and i.Status in (3,7) 
    order by i.OrderDate desc 
) as o 

或通过在status标准调整查询尝试派生表查询:

Select Distinct c.Id, c.[Name], c.Account, c.Active, o.Status, LatestDates.LatestDate 
From Customer as c 
    Left Outer Join (
     Select CustomerId, Max(OrderDate) as LatestDate 
     From [Order] i 
     where i.Status in (3,7) 
     Group By CustomerId 
    ) LatestDates On c.Id = LatestDates.CustomerId 
    Left Join [Order] o 
    on LatestDates.CustomerId = o.CustomerId 
    and LatestDates.LatestDate = o.OrderDate 
    and o.Status in (3,7) 
Where c.Active is not null 
Order by c.Active 

rextester演示所有3:http://rextester.com/WNVKL52324

所有3回:

+----+-------+---------+--------+--------+------------+ 
| Id | Name | Account | Active | Status | LatestDate | 
+----+-------+---------+--------+--------+------------+ 
| 1 | Bob | ABC  | True | NULL | NULL  | 
| 2 | Jenny | BED  | True | 7  | 2016-09-05 | 
| 3 | Tony | POT  | False | NULL | NULL  | 
| 4 | David | DON  | False | 3  | 2017-04-16 | 
+----+-------+---------+--------+--------+------------+ 
+0

谢谢你,我用你最后一次查询,因为它是我自己的修改。如果你能解释每一节,尽管确认我为什么需要它以及它是如何工作的理解,这将是一件好事。 – TechArch12

+0

奇怪的是,在一个实例中,一个实现了5个状态。你能想到为什么会这样吗? – TechArch12

+0

@ TechArch12可能是因为最后的加入。既然你加入了'CustomerId'和'LatestDate',如果有两个订单具有相同的日期,一个的状态为3,另一个状态为5,那么你会得到两个,因为最终的连接不检查'状态'再次 - 但它可以被添加到连接标准。答案已更新。 – SqlZim

1

只需使用row_number()

select c.*, o.status, o.latestdate 
from Customer c left join 
    (select o.*, 
      row_number() over (partition by o.customerId order by o.orderDate desc) as seqnum 
     from orders o 
    ) o 
    on o.customerId = c.customerId 
where seqnum = 1 and c.Active is not null 
order by c.Active; 
+0

我看不到的地方,这是考虑到状态3个7规则。 – TechArch12