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

时间:2012-12-10 08:36:48

标签: sql-server tsql query-optimization

我有这样的查询:

select * from (
    select * from TableX
    where col1 % 2 = 0
) subquery
where col1 % 4 = 0

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

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

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

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

4 个答案:

答案 0 :(得分:1)

如果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

Sql server必须先执行内部查询才能匹配第二个条件。

你也可以使用TOP(MaxInt)技巧:

select * 
from (
    select top (9223372036854775807) * 
    from TableX
    where Col1 % 2 = 0
) subquery
where Col1 % 4 = 0

在应用外部WHERE过滤器

之前,它将强制获取子查询

答案 1 :(得分:-1)

enter image description here

CREATE TABLE [dbo].[Performance](
    [Id1] [int] NOT NULL,
    [Id2] [int] NOT NULL,
    [Id3] [int] NOT NULL,
    [Description] [varchar](50) NOT NULL,
 CONSTRAINT [PK_Performance] PRIMARY KEY CLUSTERED 
(
    [Id1] ASC,
    [Id2] ASC,
    [Id3] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)

select count(*) from [Performance] = 2.000.000

select
    a.*
from
    [Performance] a
    inner join (
        select Id1,Id2,Id3,Description from [Performance] where ( id1 % 2 = 0)
    ) b on ( a.id1 = b.id1 )
where
    ( b.Id3 % 3 = 0 )

与派生表的自联接

结果返回得非常快我会说(200.000行)。

enter image description here

答案 2 :(得分:-1)

你试过了吗?

select * from ( select * from TableX as inner where inner.col1 % 2 = 0 ) as subquery where subquery.col1 % 4 = 0

我认为必须先在这里执行子查询,因为你明确地在子查询的别名结果上有where条件。

答案 3 :(得分:-2)

您可以使用cte:

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

select * from ( select * from cte ) subquery where col1 % 4 = 0