没有办法(SQL Server直到2012年的版本)针对CTE的两次出现重复使用单个后台处理程序。详细信息可以在SQLKiwi的答案中找到。再往下两次实现CTE的两种方法,这对于查询的性质是不可避免的。两种选择的净引导数均为6。
Martin的评论与Quassnoi的网站(有关指导CTE的计划)的博客上的链接是此问题的部分启发。它描述了一种为相关子查询目的实现CTE的方法,尽管相关性可能导致多次对其进行评估,但该子查询仅被引用一次。这不适用于问题中的查询。
选项1-计划指南
从SQLKiwi的答案中得到一些提示,我将指南缩减到了最低限度,该最低限度仍然可以完成工作,例如,ConstantScan
节点仅列出了2个标量运算符,它们可以充分扩展到任意数量。
;with cte(guid,other) as (
select newid(),1 union all
select newid(),2 union all
select newid(),3)
select a.guid, a.other, b.guid guidb, b.other otherb
from cte a
cross join cte b
order by a.other, b.other
OPTION(USE PLAN
N'<?xml version="1.0" encoding="utf-16"?>
<ShowPlanXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Version="1.2" Build="11.0.2100.60" xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan">
<BatchSequence>
<Batch>
<Statements>
<StmtSimple StatementCompId="1" StatementEstRows="1600" StatementId="1" StatementOptmLevel="FULL" StatementOptmEarlyAbortReason="GoodEnoughPlanFound" StatementSubTreeCost="0.0444433" StatementText="with cte(guid,other) as (
 select newid(),1 union all
 select newid(),2 union all
 select newid(),3
select a.guid, a.other, b.guid guidb, b.other otherb
from cte a
cross join cte b
order by a.other, b.other;
" StatementType="SELECT" QueryHash="0x43D93EF17C8E55DD" QueryPlanHash="0xF8E3B336792D84" RetrievedFromCache="true">
<StatementSetOptions ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" ARITHABORT="true" CONCAT_NULL_YIELDS_NULL="true" NUMERIC_ROUNDABORT="false" QUOTED_IDENTIFIER="true" />
<QueryPlan NonParallelPlanReason="EstimatedDOPIsOne" CachedPlanSize="96" CompileTime="13" CompileCPU="13" CompileMemory="1152">
<MemoryGrantInfo SerialRequiredMemory="0" SerialDesiredMemory="0" />
<OptimizerHardwareDependentProperties EstimatedAvailableMemoryGrant="157240" EstimatedPagesCached="1420" EstimatedAvailableDegreeOfParallelism="1" />
<RelOp AvgRowSize="47" EstimateCPU="0.006688" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="1600" LogicalOp="Inner Join" NodeId="0" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="0.0444433">
<OutputList>
<ColumnReference Column="Union1163" />
</OutputList>
<Warnings NoJoinPredicate="true" />
<NestedLoops Optimized="false">
<RelOp AvgRowSize="27" EstimateCPU="0.000432115" EstimateIO="0.0112613" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="40" LogicalOp="Sort" NodeId="1" Parallel="false" PhysicalOp="Sort" EstimatedTotalSubtreeCost="0.0117335">
<OutputList>
<ColumnReference Column="Union1080" />
<ColumnReference Column="Union1081" />
</OutputList>
<MemoryFractions Input="0" Output="0" />
<Sort Distinct="false">
<OrderBy>
<OrderByColumn Ascending="true">
<ColumnReference Column="Union1081" />
</OrderByColumn>
</OrderBy>
<RelOp AvgRowSize="27" EstimateCPU="4.0157E-05" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="40" LogicalOp="Constant Scan" NodeId="2" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="4.0157E-05">
<OutputList>
<ColumnReference Column="Union1080" />
<ColumnReference Column="Union1081" />
</OutputList>
<ConstantScan>
<Values>
<Row>
<ScalarOperator ScalarString="newid()">
<Intrinsic FunctionName="newid" />
</ScalarOperator>
<ScalarOperator ScalarString="(1)">
<Const ConstValue="(1)" />
</ScalarOperator>
</Row>
<Row>
<ScalarOperator ScalarString="newid()">
<Intrinsic FunctionName="newid" />
</ScalarOperator>
<ScalarOperator ScalarString="(2)">
<Const ConstValue="(2)" />
</ScalarOperator>
</Row>
</Values>
</ConstantScan>
</RelOp>
</Sort>
</RelOp>
<RelOp AvgRowSize="27" EstimateCPU="0.0001074" EstimateIO="0.01" EstimateRebinds="0" EstimateRewinds="39" EstimatedExecutionMode="Row" EstimateRows="40" LogicalOp="Lazy Spool" NodeId="83" Parallel="false" PhysicalOp="Table Spool" EstimatedTotalSubtreeCost="0.0260217">
<OutputList>
<ColumnReference Column="Union1162" />
<ColumnReference Column="Union1163" />
</OutputList>
<Spool>
<RelOp AvgRowSize="27" EstimateCPU="0.000432115" EstimateIO="0.0112613" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="40" LogicalOp="Sort" NodeId="84" Parallel="false" PhysicalOp="Sort" EstimatedTotalSubtreeCost="0.0117335">
<OutputList>
<ColumnReference Column="Union1162" />
<ColumnReference Column="Union1163" />
</OutputList>
<MemoryFractions Input="0" Output="0" />
<Sort Distinct="false">
<OrderBy>
<OrderByColumn Ascending="true">
<ColumnReference Column="Union1163" />
</OrderByColumn>
</OrderBy>
<RelOp AvgRowSize="27" EstimateCPU="4.0157E-05" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="40" LogicalOp="Constant Scan" NodeId="85" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="4.0157E-05">
<OutputList>
<ColumnReference Column="Union1162" />
<ColumnReference Column="Union1163" />
</OutputList>
<ConstantScan>
<Values>
<Row>
<ScalarOperator ScalarString="newid()">
<Intrinsic FunctionName="newid" />
</ScalarOperator>
<ScalarOperator ScalarString="(1)">
<Const ConstValue="(1)" />
</ScalarOperator>
</Row>
<Row>
<ScalarOperator ScalarString="newid()">
<Intrinsic FunctionName="newid" />
</ScalarOperator>
<ScalarOperator ScalarString="(2)">
<Const ConstValue="(2)" />
</ScalarOperator>
</Row>
</Values>
</ConstantScan>
</RelOp>
</Sort>
</RelOp>
</Spool>
</RelOp>
</NestedLoops>
</RelOp>
</QueryPlan>
</StmtSimple>
</Statements>
</Batch>
</BatchSequence>
</ShowPlanXML>'
);
选项2-远程扫描
通过增加查询费用并引入远程扫描,结果得以实现。
with cte(guid,other) as (
select *
from OPENQUERY([TESTSQL\V2012], '
select newid(),1 union all
select newid(),2 union all
select newid(),3') x)
select a.guid, a.other, b.guid guidb, b.other otherb
from cte a
cross join cte b
order by a.other, b.other;