2017-05-03 105 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