CTE多次执行

时间:2013-01-31 12:30:59

标签: sql-server-2008-r2 common-table-expression

我有这个结构:

WITH my_cte
    AS
    (
    SELECT y.name
    FROM 
        WHData.dbo.vw_data x
        INNER JOIN WHData.dbo.vw_DimNames y
                ON x.nameKey = y.CasinoKey
    WHERE DateKey >= CONVERT(CHAR(8),DATEADD(mm,-2,GETDATE() - DAY(GETDATE())) + 1,112)--two complete months ago    
    GROUP BY y.name
    )
SELECT *
FROM    WHAnalysis.dbo.tb_otherData a
WHERE   NOT EXISTS
                (
            SELECT 1
            FROM my_cte b
            WHERE b.name = a.name 
            );

如果我单独运行CTE中的代码,则需要3秒;但是完整的脚本只是运行并运行。

如果我离开CTE并使用索引的临时表,则它全部以4秒运行。

我认为正在发生的是CTE正在对tb_otherData中的每个数据记录执行所以它可能需要,因为有2000条记录,2000 x 3秒....长!

临时表解决方案很好但是,出于兴趣,有没有办法更改CTE代码以便它快速运行?我缺少一些CTE技巧吗?


修改

如果我切换到一个好的老式子查询,那么执行计划绝对相同:

SELECT *
FROM   WHAnalysis.dbo.tb_otherData a
WHERE name not in 
        (
            SELECT y.name
            FROM 
            WHData.dbo.vw_data x
            INNER JOIN WHData.dbo.vw_DimNames y
            ON x.nameKey = y.CasinoKey
             WHERE DateKey >= CONVERT(CHAR(8),DATEADD(mm,-2,GETDATE() - DAY(GETDATE())) + 1,112)--two complete months ago   
              GROUP BY y.name
              );

1 个答案:

答案 0 :(得分:2)

尝试使用此查询而不是使用带有EXISTS的子查询:

SELECT a. *
FROM    WHAnalysis.dbo.tb_otherData a
LEFT JOIN
(   SELECT y.name as name
    FROM WHData.dbo.vw_data x
         INNER JOIN WHData.dbo.vw_DimNames y
                ON x.nameKey = y.CasinoKey
         WHERE DateKey >= 
          CONVERT(CHAR(8),DATEADD(mm,-2,GETDATE() - DAY(GETDATE())) + 1,112)    
) b on a.name=b.name
WHERE b.name is null

如果DateKey来自WHData.dbo.vw_data,那么它将是:

SELECT a. *
FROM    WHAnalysis.dbo.tb_otherData a
LEFT JOIN WHData.dbo.vw_DimNames y on a.name=y.name
LEFT JOIN WHData.dbo.vw_data x
   on y.CasinoKey= x.nameKey 
      and (
          x.DateKey >= 
          CONVERT(CHAR(8),DATEADD(mm,-2,GETDATE() - DAY(GETDATE())) + 1,112)
          )
WHERE x.nameKey is null