2009-12-17 6 views
0
sous-table

Je veux optimiser cette requêteOptimizing requête T-SQL qui constracts même deux fois


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) 

Alors que la table


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 

construit une seule fois. Mais quand je le déclare comme une table temporaire, le temps d'exécution augmente plusieurs fois. Y a-t-il un moyen de l'optimiser en construisant cette table une fois? Y a-t-il un moyen de l'optimiser d'une manière ou d'une autre?

Nous vous remercions de votre aide.

+0

S'il vous plaît nettoyer et reformater votre sql il est impossible de lire .. par exemple, ce qui est « dbo.tFoundWords.WordFromKladr » –

+0

Pourquoi ne pas vous aussi propre et reformater votre nom. Peut-être grandir un peu. –

+0

J'ai changé votre nom d'utilisateur pour vous. S'il vous plaît noter que le blasphème est fortement déconseillé sur Stack Overflow. C'est parce que le site est principalement utilisé dans le lieu de travail, et nous ne voulons pas être bloqués par les politiques de l'entreprise de quiconque en raison de profanation. –

Répondre

0

Vous pouvez créer deux CTEs dans un communiqué. Essayez ceci:

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) 
+0

Merci, on dirait que ça fonctionne ... – StuffHappens

+0

Votre tout à fait bienvenue ... En passant, bien que vous soyez bien sûr libre de formater et de coder comme vous le trouvez le plus agréable, il va sans dire que le SQL est plus lisible Dans votre question, plus vous participerez et plus vous aurez d'autres personnes sur ce forum. Il y a quelques techniques généralement acceptées pour rendre de longues instructions SQL plus lisibles ... Bien que je ne sous-entend pas que la façon dont j'ai formaté le SQL ci-dessus soit la meilleure, notez par exemple les alias de table que j'ai ajoutés à votre code. –

1

Utilisation:

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) 
... 
Questions connexes