13

我有一个这样的查询:

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

4 回答 4

19

如果您的 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它会在应用外部过滤器之前强制获取子查询

于 2018-04-18T12:46:14.057 回答
-1

在此处输入图像描述

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 行)。

在此处输入图像描述

于 2015-12-24T13:48:16.227 回答
-1

你有没有尝试过:

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

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

于 2017-12-09T17:29:35.173 回答
-4

您可以为此使用 cte:

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

select * from ( select * from cte ) subquery where col1 % 4 = 0
于 2012-12-10T08:51:09.173 回答