我如何强制sql server首先执行子查询并过滤'where'语句

Kev*_*ang 9 t-sql sql-server query-optimization

我有这样的查询:

select * from (
    select * from TableX
    where col1 % 2 = 0
) subquery
where col1 % 4 = 0
Run Code Online (Sandbox Code Playgroud)

实际的子查询更复杂.当我单独执行子查询时,它可以快速返回200个,但是当我执行整个查询时,等待时间太长.

我知道sql server在这里进行了一些优化,并将where语句合并到子查询中,并产生了效率不高的新执行计划.虽然我可以深入了解执行计划并分析为什么,如索引缺失,统计数据陈旧.

但我肯定知道,我的子查询作为BaseTable将只返回一小部分数据,所以我希望所有进一步的过滤或加入只会发生在这些小部分数据中.

我的问题是,我可以强制sql server首先执行子查询,而不关心外部where语句吗?(顺便说一句,TempTable是我的最后一个选择,CTE无效)

Mtw*_*ark 7

如果您的TableX中有一个关键列,则可以使用自我连接:

select x1.* 
from TableX x1
inner join  (
    select x.IdColumn 
    from TableX x
    where x.Col1 % 2 = 0
) x2 on x1.IdColumn = x2.IdColumn
where x1.Col1 % 4 = 0
Run Code Online (Sandbox Code Playgroud)

SQL服务器必须先执行内部查询才能匹配第二个条件。

您还可以使用TOP(MaxInt)技巧:

select * 
from (
    select top (9223372036854775807) * 
    from TableX
    where Col1 % 2 = 0
) subquery
where Col1 % 4 = 0
Run Code Online (Sandbox Code Playgroud)

在应用外部WHERE过滤器之前,它将强制获取子查询

  • “TOP”救了我的命。我发疯了,因为我的子查询很好,但忽略了 `where`,这导致了转换错误。 (5认同)
  • 美丽的黑客:) (2认同)

Moh*_*dey -5

您可以使用 cte 来实现:

with cte as(
 select * from TableX where col1 % 2 = 0 
)

select * from ( select * from cte ) subquery where col1 % 4 = 0
Run Code Online (Sandbox Code Playgroud)

  • 这并不强制任何特定的评估顺序。SQL Server 将仅合并两个查询,就像 OP 中的派生表一样。 (4认同)