2010-11-10 55 views
0

我有一个历史记录表,其中包含每次记录更改时的快照。我试图用原始捕获日期返回某个历史记录行。我目前正在使用这个此刻:查找结果的第一行

select 
    s.Description, 
    h.CaptureDate OriginalCaptureDate 
from 
    HistoryStock s 
    left join 
     (select 
       StockId, 
       CaptureDate 
      from 
       HistoryStock 
      where 
       HistoryStockId in (select MIN(HistoryStockId) from HistoryStock group by StockId) 
     ) h on s.StockId = h.StockId 
where 
    s.HistoryStockId = @HistoryStockId 

这工作,但有1万条记录其对慢侧,我不知道如何优化这个查询。

此查询如何优化?

UPDATE

WITH OriginalStock (StockId, HistoryStockId) 
AS (
    SELECT StockId, min(HistoryStockId) 
    from HistoryStock group by StockId 
    ), 
OriginalCaptureDate (StockId, OriginalCaptureDate) 
As (
    SELECT h.StockId, h.CaptureDate 
    from HistoryStock h join OriginalStock o on h.HistoryStockId = o.HistoryStockId 
) 

select 
    s.Description, 
    h.OriginalCaptureDate 
from 
    HistoryStock s left join OriginalCaptureDate h on s.StockId = h.StockId 
where 
    s.HistoryStockId = @HistoryStockId 

我已经更新到使用CTE的代码,但我没有更好的性能明智的,只有微小的性能提升。有任何想法吗?

只是另一个说明,我需要查看StockId的历史记录表中的第一条记录,而不是最早的捕获日期。

+0

您正在使用HistoryStockId限制最终查询,我认为它只限于一个StockId,但看起来您将加入所有历史记录以获得此结果。您是否尝试过使用参数@HistoryStockId限制CTE?发布查询的执行计划将有所帮助。 – Tony 2010-11-10 13:38:50

+0

您能向我们展示“HistoryStock”所有相关列的列架构吗? (这里是唯一的表格,对吗?) – AakashM 2010-11-10 13:48:35

+0

您似乎有一个额外的CTE,它是多余的,据我所见,OriginalCaptureDate是不必要的 - 为什么不根据它进行最终选择并选择您感兴趣的字段?。如果INNER JOIN适合,您也正在执行LEFT JOIN。如上所述,您还可以在声明的最后一点对historystockid进行过滤 - 为什么不首先对此进行过滤以减少正在检查的数据集? – JamWheel 2010-11-16 09:05:58

回答

1

我不确定我完全理解数据如何在您的查询中工作,但嵌套这样的查询在我看来对性能没有好处。你可以尝试一下:

WITH MinCaptureDate (StockID, MinCaptureDate) 
AS (
    SELECT HS.StockID 
     ,MIN(HS.CaptureDate) AS OriginalCaptureDate 
    FROM HistoryStock HS 
    GROUP BY 
     HS.Description 
    ) 
SELECT HS.Description 
    ,MCD.OriginalCaptureDate 
FROM HistoryStock HS 
JOIN MinCaptureDate MCD 
    ON HS.StockID = MCD.StockID 
WHERE HS.StockID = @StockID 
+0

感谢您对CTE的建议,但调整我的查询以使用CTE只会让我的性能提升2秒。任何其他想法? – adriaanp 2010-11-10 10:47:22

+0

@adriaanp:你说速度提高了2秒,你查询的执行时间是多少?我一直在使用一些随机数据进行测试,并且您的查询在我的服务器上的<1s内返回,使用300万条记录...... SQL框的规格是什么? – Tony 2010-11-10 14:41:19

0

我想我明白你想达到什么。你基本上要指定历史记录股票的说明,但你想用股票第一历史记录相关的日期......所以,如果你的历史表看起来像这样

StockId HistoryStockId CaptureDate Description 
1   1    Apr 1   Desc 1 
1   2    Apr 2   Desc 2 
1   3    Apr 3   Desc 3 

,并指定@HistoryStockId = 2,你想要的结果如下

Description OriginalCaptureDate 
Desc 2  Apr 1 

我觉得下面的查询会给你一个稍微好一点的性能。

WITH OriginalStock (StockId, CaptureDate, RowNumber) 
AS ( 
    SELECT 
     StockId, 
     CaptureDate, 
     RowNumber = ROW_NUMBER() OVER (PARTITION BY StockId ORDER BY HistoryStockId ASC) 
    from HistoryStock 
    ) 

select 
    s.Description, 
    h.CaptureDate 
from 
    HistoryStock s left join OriginalStock h on s.StockId = h.StockId and h.RowNumber = 1 
where 
    s.HistoryStockId = @HistoryStockId 
+0

您有语法错误,请在WITH子句后面删除“,”。此外,这个查询在我的测试中的表现比其他人已经提出的要差很多。 – Tony 2010-11-11 08:25:07