1

私はこの構造を持っています:

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
              );
4

1 に答える 1

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
于 2013-01-31T13:17:10.587 に答える