优化两次构造同一子表的T-SQL查询

优化两次构造同一子表的T-SQL查询,sql,sql-server,sql-server-2005,tsql,Sql,Sql Server,Sql Server 2005,Tsql,我想优化这个查询 WITH CTE AS ( SELECT KladrItemName _KladrItemName , WordPositionKladrItem _WordPositionKladrItem , WordPositionAddressString _WordPositionAddressString , StartPosition

我想优化这个查询


WITH CTE AS
(
    SELECT 
          KladrItemName                 _KladrItemName
        , WordPositionKladrItem         _WordPositionKladrItem
        , WordPositionAddressString     _WordPositionAddressString
        , StartPosition                 _StartPosition
        , EndPosition                   _EndPosition
        , Metric                        _Metric
        , IsConstruction                _IsConstruction
        , WordsCount                    _WordsCount
        , Indeces                       _Indeces
        , WordPositionAddressString     _StartWordIndex
        , WordPositionAddressString     _EndWordIndex
        , 1                             _StepNumber
    FROM 
        (
        SELECT 
            dbo.tKladrItems.KladrItemName
            , dbo.tFoundWords.WordFromAddressString 
            , dbo.tFoundWords.WordFromKladr 
            , dbo.tFoundWords.WordPosition AS WordPositionAddressString
            , dbo.tWordKladrItems.wordNumber AS WordPositionKladrItem
            , dbo.tFoundWords.StartPosition
            , dbo.tFoundWords.EndPosition
            , dbo.tFoundWords.Metric
            , dbo.tFoundWords.IsConstruction
            , dbo.tKladrItems.WordsCount
            , dbo.tKladrItems.Indeces
        FROM
            dbo.tWordsFromKladr JOIN dbo.tWordKladrItems ON dbo.tWordsFromKladr.ID = dbo.tWordKladrItems.wordID 
            JOIN dbo.tFoundWords ON dbo.tFoundWords.WordFromKladr = dbo.tWordsFromKladr.WordFromKladr
            JOIN dbo.tKladrItems ON dbo.tWordKladrItems.kladrItemID = dbo.tKladrItems.id    
        )T
    UNION ALL
    SELECT
          KladrItemName
        , WordPositionKladrItem
        , WordPositionAddressString
        , CASE WHEN StartPosition  _EndPosition THEN EndPosition ELSE _EndPosition END -- MAX
        , CAST(Metric + _Metric AS numeric(20, 10))
        , IsConstruction + _IsConstruction
        , WordsCount
        , Indeces
        , CASE WHEN _StartWordIndex  WordPositionAddressString THEN _EndWordIndex ELSE WordPositionAddressString END
        , 1 + _StepNumber
    FROM 

        (
        SELECT 
            dbo.tKladrItems.KladrItemName
            , dbo.tFoundWords.WordFromAddressString 
            , dbo.tFoundWords.WordFromKladr 
            , dbo.tFoundWords.WordPosition AS WordPositionAddressString
            , dbo.tWordKladrItems.wordNumber AS WordPositionKladrItem
            , dbo.tFoundWords.StartPosition
            , dbo.tFoundWords.EndPosition
            , dbo.tFoundWords.Metric
            , dbo.tFoundWords.IsConstruction
            , dbo.tKladrItems.WordsCount
            , dbo.tKladrItems.Indeces
        FROM
            dbo.tWordsFromKladr JOIN dbo.tWordKladrItems ON dbo.tWordsFromKladr.ID = dbo.tWordKladrItems.wordID 
            JOIN dbo.tFoundWords ON dbo.tFoundWords.WordFromKladr = dbo.tWordsFromKladr.WordFromKladr
            JOIN dbo.tKladrItems ON dbo.tWordKladrItems.kladrItemID = dbo.tKladrItems.id
        ) AS Tab JOIN CTE ON
            Tab.KladrItemName = CTE._KladrItemName
        AND Tab.WordPositionKladrItem > CTE._WordPositionKladrItem
        AND Tab.WordPositionAddressString >  CTE._WordPositionAddressString
)
SELECT DISTINCT 

      _KladrItemName        KladrItemName
    , _StartPosition        StartPosition
    , _EndPosition          EndPosition
    , _Metric               SumMetric
    , _IsConstruction       SumIsConstruction
    , _Indeces              Indeces

FROM 
    CTE
WHERE 
    _StepNumber = _WordsCount
    AND (_IsConstruction = 0 or (_IsConstruction = 1 and _WordsCount > 1))
    AND _EndWordIndex - _StartWordIndex + 1 = _WordsCount
option (maxrecursion 0) 
所以那张桌子


SELECT 
            dbo.tKladrItems.KladrItemName
            , dbo.tFoundWords.WordFromAddressString 
            , dbo.tFoundWords.WordFromKladr 
            , dbo.tFoundWords.WordPosition AS WordPositionAddressString
            , dbo.tWordKladrItems.wordNumber AS WordPositionKladrItem
            , dbo.tFoundWords.StartPosition
            , dbo.tFoundWords.EndPosition
            , dbo.tFoundWords.Metric
            , dbo.tFoundWords.IsConstruction
            , dbo.tKladrItems.WordsCount
            , dbo.tKladrItems.Indeces
        FROM
            dbo.tWordsFromKladr JOIN dbo.tWordKladrItems ON dbo.tWordsFromKladr.ID = dbo.tWordKladrItems.wordID 
            JOIN dbo.tFoundWords ON dbo.tFoundWords.WordFromKladr = dbo.tWordsFromKladr.WordFromKladr
            JOIN dbo.tKladrItems ON dbo.tWordKladrItems.kladrItemID = dbo.tKladrItems.id
只生成一次。但当我将其声明为临时表时,执行时间会增加几倍。有没有办法通过一次构建这个表来优化它?有没有其他方法可以优化它

谢谢您的帮助。

使用:

WITH base_table AS (
    SELECT wki.KladrItemName, 
           fw.WordFromAddressString, 
           fw.WordFromKladr, 
           fw.WordPosition AS WordPositionAddressString,
           tfk.wordNumber AS WordPositionKladrItem,
           fw.StartPosition,
           fw.EndPosition,
           fw.Metric,
           fw.IsConstruction,
           wki.WordsCount,
           wki.Indeces
      FROM dbo.tWordsFromKladr tfk
      JOIN dbo.tWordKladrItems wki ON wki.wordID = tkf.ID 
      JOIN dbo.tFoundWords fw ON fw.WordFromKladr = tfk.WordFromKladr
      JOIN dbo.tKladrItems ki ON ki.id = wki.kladrItemID),
     cte AS (
     SELECT bt.*
      FROM base_table bt
     UNION ALL
     SELECT KladrItemName, 
            WordPositionKladrItem, 
            WordPositionAddressString, 
            CASE WHEN StartPosition  _EndPosition THEN EndPosition ELSE _EndPosition END -- MAX, 
            CAST(Metric + _Metric AS numeric(20, 10)), 
            IsConstruction + _IsConstruction,
            WordsCount, 
            Indeces, 
            CASE WHEN _StartWordIndex  WordPositionAddressString THEN _EndWordIndex ELSE WordPositionAddressString END,
            1 + _StepNumber
       FROM base_table)
...

您可以在一条语句中创建两个CTE。试试这个:

WITH Sub As
 (SELECT i.KladrItemName,
            f.WordFromAddressString, f.WordFromKladr,
            f.WordPosition WordPositionAddressString,
            wi.wordNumber WordPositionKladrItem,
            f.StartPosition, f.EndPosition, f.Metric, 
            f.IsConstruction, i.WordsCount, i.Indeces         
         FROM dbo.tWordsFromKladr w
            JOIN dbo.tWordKladrItems wi ON wi.ID = i.wordID                 
            JOIN dbo.tFoundWords f ON f.WordFromKladr = w.WordFromKladr
            JOIN dbo.tKladrItems i ON wi.kladrItemID = i.id ),
   CTE As
 (SELECT KladrItemName _KladrItemName, 
      WordPositionKladrItem _WordPositionKladrItem, 
      WordPositionAddressString _WordPositionAddressString, 
      StartPosition _StartPosition ,  
      EndPosition _EndPosition,
      Metric _Metric, IsConstruction _IsConstruction,
      WordsCount _WordsCount,
      Indeces _Indeces,
      WordPositionAddressString _StartWordIndex ,
      WordPositionAddressString _EndWordIndex,
      1 _StepNumber     
   FROM Sub T    
    UNION ALL    
 SELECT KladrItemName, WordPositionKladrItem, WordPositionAddressString,
      CASE WHEN StartPosition < _EndPosition 
            THEN EndPosition ELSE _EndPosition END, -- Max
      CAST(Metric + _Metric AS numeric(20, 10)),
      IsConstruction + _IsConstruction, 
      WordsCount, Indeces,
      CASE WHEN _StartWordIndex  WordPositionAddressString 
           THEN _EndWordIndex ELSE WordPositionAddressString END, 
      1 + _StepNumber
 FROM Sub Tab
    JOIN CTE                
       ON Tab.KladrItemName = CTE._KladrItemName        
          AND Tab.WordPositionKladrItem > CTE._WordPositionKladrItem        
          AND Tab.WordPositionAddressString >  CTE._WordPositionAddressString)
SELECT DISTINCT _KladrItemName KladrItemName,
    _StartPosition  StartPosition,  _EndPosition EndPosition,
    _Metric  SumMetric,_IsConstruction SumIsConstruction,
    _Indeces Indeces 
FROM CTE
WHERE_StepNumber = _WordsCount    
    AND (_IsConstruction = 0 or (_IsConstruction = 1 and _WordsCount > 1))        
    AND _EndWordIndex - _StartWordIndex + 1 = _WordsCountoption     
 (maxrecursion 0) 

请清理并重新格式化sql,因为无法读取。。e、 例如,什么是dbo.tFoundWords.WordFromKladr为什么不清理并重新格式化您的名称。也许长大一点。我为你更改了你的用户名。请注意,在堆栈溢出时强烈反对亵渎。这是因为该网站主要用于工作场所,我们不想因为亵渎而被任何人的公司政策所阻止。非常欢迎。。。顺便说一句,虽然您当然可以自由地按照自己认为最合适的方式进行格式化和编码,但不用说,您的问题中的SQL越可读、越清晰,您将从论坛上的其他人那里获得更多的参与和帮助。有一些公认的技术可以使长SQL语句更具可读性。。。虽然我并不是在暗示我如何格式化上面的SQL是最好的,但是请注意,例如,我添加到代码中的表别名。