2012-07-12 48 views
0
Account 
======= 
int AccountId PK 

Order 
===== 
int OrderId PK 
int AccountId FK 
DateTime Date 
int Status 

對於每個帳戶,我想知道最近的狀態爲1(成功)的訂單,否則狀態爲0的最近訂單(不成功)。日期不是唯一的。正在尋找替代T-SQL子查詢

我已經得到了這個工作,在這樣的視圖相關子查詢...

SELECT 
    a.AccountId, 
    (SELECT TOP 1 
      o.orderId 
     FROM 
      tbl_order o 
     WHERE 
      o.Accountid = a.AccountId 
      AND 
      o.Status IN (0, 1) 
     ORDER BY 
      o.Status DESC, o.Date DESC 
     ) AS OrderId 
FROM 
    tbl_account a 

...但它緩慢。

有沒有更好的方法?

+2

沒有什麼不對您的查詢或子查詢。在任何現代版本的SQL Server中,相關子查詢都比任何其他正確的做同樣事情的正確方法都慢(2000年和更早的版本確實存在這個問題),這是個神話。這裏的緩慢幾乎可以肯定是來自貧困/缺席指數或其他原因。如果您提供查詢計劃和/或包括密鑰和索引在內的表定義,我們可以爲您提供更好的幫助。 – RBarryYoung 2012-07-12 22:11:20

+0

我想你可能有一點。上面的視圖似乎立即自行運行,但當我從另一個角度加入時,視圖很慢。它做一個'嵌套循環 - 外連接。對於頂部(外部)輸入中的每一行,掃描底部(內部)輸入,並輸出匹配的行。'這對我來說聽起來不太熱! :) – 2012-07-12 23:33:52

+0

你是對的@RBarryYoung - 子查詢工作正常。所以我有視圖A和視圖B和B包含來自我的問題的查詢。當A連接到B時,它運行緩慢。當A和B分開時,它們運行良好。使得這兩者的組合運行緩慢的因素似乎是在派生表內的視圖A中的單個連接。它是一個正常的連接,我已經能夠移動到其他位置 - 在派生表外部。所以這真的很奇怪,而且我目前還沒有真正有能力執行計劃中的變更,因爲這會導致這... – 2012-07-13 01:01:43

回答

3

你可以使用一個CTE與ROW_NUMBER功能:

WITH cte AS(
    SELECT a.AccountId, o.OrderId, o.Date, o.Status 
    , RN = ROW_NUMBER()OVER(Partition By a.AccountId ORDER BY o.Status DESC, o.Date DESC) 
    FROM Account a 
    LEFT OUTER JOIN [Order] o ON a.AccountId = o.AccountId 
) 
SELECT AccountId, OrderId 
FROM cte 
WHERE RN = 1 

這裏有一個小提琴:http://sqlfiddle.com/#!3/4e1e3/4/0

+1

OP的查詢不是作爲「LEFT OUTER JOIN」並返回_all_帳戶嗎? – HABO 2012-07-13 00:11:01

+0

@ user92546:是的,我認爲你是對的。相應地編輯我的答案。還改變了'ROW_NUMBER'在AccountId上做Partition By,因爲我認爲這是OP所需要的。 – 2012-07-13 07:12:51

+0

看起來很酷@TimSchmelter。我認爲你已經回答了這個問題,但事實證明,我的子查詢本身並不是減速的原因。我從來沒有聽說過'分區'。 – 2012-07-13 12:55:36

0

試試這個:

SELECT 
    a.AccountId, 
     o.OrderId 
FROM 
    tbl_account a OUTER APPLY 
     (
      SELECT TOP 1 o.orderId 
     FROM tbl_order o 
     WHERE o.Accountid = a.AccountId 
     AND o.Status IN (0, 1) 
     ORDER BY o.Status DESC, o.Date DESC 
    ) AS o 
+0

外部應用匹配OP的隱含的LEFT JOIN邏輯。 – ErikE 2012-07-13 04:11:03

+0

@ErikE你是對的。更新了答案。 – Chandu 2012-07-13 14:49:29