2012-07-12 54 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