How can i force sql server to execute subquery first and filter the 'where' statement

筅森魡賤 提交于 2019-12-22 04:08:51

问题


i have a query like this:

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

The actual subquery is more complicated. when i execute the subquery alone it returns maybe 200rows quickly, but when i execute the whole query, it takes too long to wait.

I know sql server takes some optimization here and merge the where statement into the subquery, and produce the new execution plan which is not that efficient. Althought i can dive into the execution plan and analyze why, like index missing, statistics stale.

But i surely know that, my subquery which serves as a BaseTable will only return a small portion of data, so i want all further filtering or joining will only take place in these small portion of data.

My question is, can i force sql server to execute the subquery first, without caring about the outer where statement? (btw, TempTable is my last option, CTE is not working)


回答1:


If you have a key column in your TableX you can use a Self Join:

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 will have to execute the inner query before to match the second condition.

You could use also the TOP(MaxInt) trick:

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

It will force to get subquery before apply the outer WHERE filter




回答2:


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 )

Self join with derived table

Results returned pretty fast I would say (200.000 rows).




回答3:


Have you tried:

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

I believe it has to execute the subquery first here because you're explicitly having the where condition on the aliased result of the subquery.




回答4:


You can use cte for that:

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

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


来源:https://stackoverflow.com/questions/13797411/how-can-i-force-sql-server-to-execute-subquery-first-and-filter-the-where-stat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!