优化两次构造同一子表的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是最好的,但是请注意,例如,我添加到代码中的表别名。