替换Subselect以获得更高效的效果

时间:2013-08-02 13:02:34

标签: tsql sql-server-2008-r2

我有这个查询需要很长时间,部分是因为表中的记录数量超过了50万条记录,但我必须使用的联接减慢了很多,至少对我的信念来说

SELECT TOP (10) PERCENT H1.DateCompteur, CASE WHEN (h1.cSortie - h2.cSortie > 0)         
THEN h1.cSortie - h2.cSortie ELSE 0 END AS Compte, H1.IdMachine
FROM dbo.T_HistoriqueCompteur AS H1 INNER JOIN
     dbo.T_HistoriqueCompteur AS H2 ON H1.IdMachine = H2.IdMachine AND H2.DateCompteur =
     (SELECT MAX(DateCompteur) AS Expr1
        FROM dbo.T_HistoriqueCompteur AS HS
       WHERE (DateCompteur < H1.DateCompteur) AND (H1.IdMachine = IdMachine))
ORDER BY H1.DateCompteur DESC

顺序是重要的,因为我只需要最新的信息。我尝试在子选择中使用ID字段,因为它们按日期排序,但无法检测到任何显着的改进。

SELECT TOP (10) PERCENT H1.DateCompteur, CASE WHEN (h1.cSortie - h2.cSortie > 0)         
THEN h1.cSortie - h2.cSortie ELSE 0 END AS Compte, H1.IdMachine
FROM dbo.T_HistoriqueCompteur AS H1 INNER JOIN
     dbo.T_HistoriqueCompteur AS H2 ON H1.IdMachine = H2.IdMachine AND H2.ID =
     (SELECT MAX(ID) AS Expr1
        FROM dbo.T_HistoriqueCompteur AS HS
       WHERE (ID < H1.ID) AND (H1.IdMachine = IdMachine))
ORDER BY H1.DateCompteur DESC

我使用的表看起来有点像这样(我有更多列,但它们在此查询中未使用)。

ID bigint
IdMachine bigint
cSortie bigint
DateCompteur datetime

我认为如果我能摆脱子选择,我的查询运行速度会快得多,但我真的找不到办法。我真正想要做的是找到具有相同IdMachine的前一行,以便我可以计算两个cSortie值之间的差异。查询中的情况是因为它被重置为0,在这种情况下,我想返回0而不是负值。

所以我的问题是:我能做得比我已经拥有的更好吗?如果这会产生影响,我打算把它放在一个视图中。

2 个答案:

答案 0 :(得分:0)

尝试此查询

WITH T as
(
  SELECT TOP (10) PERCENT H1.DateCompteur, H1.cSortie as cSortie1, H1.IdMachine,
  (
        SELECT TOP 1 H2.cSortie
        FROM dbo.T_HistoriqueCompteur H2
        WHERE (H2.DateCompteur < H1.DateCompteur) AND (H1.IdMachine = H2.IdMachine)
        ORDER BY H2.DateCompteur DESC   
  ) as cSortie2
  FROM dbo.T_HistoriqueCompteur AS H1
  ORDER BY H1.DateCompteur DESC 
)

select DateCompteur, 
       CASE WHEN (cSortie1 - cSortie2 > 0)         
            THEN cSortie1 - cSortie2 
            ELSE 0 END 
            AS Compte, 
       IdMachine
FROM T

答案 1 :(得分:0)

您还可以尝试使用窗口函数(ROW_NUMBER)的CTE(公用表表达式):

;WITH CTE AS
(
    SELECT ID,IdMachine,cSortie,ROW_NUMBER() OVER(PARTITION BY h.IdMachine ORDER BY ID ASC) AS [ROW] 
    FROM T_HistoriqueCompteur h
)
SELECT 
    TOP (10) PERCENT 
        H1.DateCompteur,
        CASE WHEN (h1.cSortie - h2.cSortie > 0) THEN h1.cSortie - h2.cSortie 
            ELSE 0 
        END AS Compte,
        H1.IdMachine
FROM dbo.T_HistoriqueCompteur AS H1 
INNER JOIN CTE cte on cte.idmachine = h1.idmachine and cte.id = h1.id
INNER JOIN CTE h2 on h2.idmachine = cte.idmachine and h2.row + 1 = cte.row
ORDER BY H1.DateCompteur DESC