它是如何工作的? - 查询中的多个子选择

Posted

技术标签:

【中文标题】它是如何工作的? - 查询中的多个子选择【英文标题】:How does it works? - Multiple SubSelect in Query 【发布时间】:2020-06-24 19:44:02 【问题描述】:

我有一个由 PowerBi Desktop 的 QueryFolding 生成的查询。 我试图了解它是如何工作的。 我可以看到有一个大查询,带有嵌套的子选择。

如果我运行此查询,则需要大约 1 秒才能完成。 但是当我运行第二个查询时,即多个子选择的内部查询,这大约需要两分钟。

那么,SQL Server 是如何处理子选择中的 TOP 1000 或 WHERE 的呢? 为什么内部查询比整个查询慢?

谢谢!!

整个查询(更快)

select top 1000
    [_].[NOMBRE_1] as [NOMBRE_1],
    [_].[SUSCRIPCIO] as [SUSCRIPCIO],
    [_].[ANOMES] as [ANOMES],
    1 as [Rut]
from 
(
    select [_].[NOMBRE_1],
        [_].[SUSCRIPCIO],
        [_].[ANOMES]
    from 
    (
        select [NOMBRE_1],
            [SUSCRIPCIO],
            [ANOMES]
        from [dbo].[TABLE] as [$Table]
    ) as [_]
    where [_].[SUSCRIPCIO] >= convert(datetime2, '2020-01-01 00:00:00') and [_].[SUSCRIPCIO] <= convert(datetime2, '2020-02-01 00:00:00')
) as [_]

内部子选择(较慢)

select [NOMBRE_1],
    [SUSCRIPCIO],
    [ANOMES]
from [dbo].[TABLE] as [$Table]

【问题讨论】:

我不得不问,为什么你会选择将你的对象别名为 [_][$Table] 我没有选择那个。该代码是由 PowerBi 的“QueryFolding”功能“自动”生成的(顺便说一句,我讨厌它) 【参考方案1】:

因为整个查询包含两个过滤器:

where [_].[SUSCRIPCIO] >= convert(datetime2, '2020-01-01 00:00:00') and [_].[SUSCRIPCIO] <= convert(datetime2, '2020-02-01 00:00:00')

top 1000

这极大地限制了查询返回的值,使查询运行得更快。另一方面,内部查询没有过滤器,因此它必须返回完整的结果集。如果 [$Table] 有很多行,那么这可能是一个漫长的过程

【讨论】:

谢谢。但奇怪的是,外查询使用内查询,外查询比内查询快。那么,我是否应该假设 SQL Server 能够使用外部查询的 WHERE 过滤内部查询? 正确。外部查询中的过滤器意味着它只需要从内部查询中获取一组有限的值。它不会先完全评估内部查询然后对其进行过滤,而是在满足条件之前进行过滤。就像您有一个包含数百万行的表并使用“select top 10 *”对其进行过滤一样,它不会尝试选择所有行然后只返回前 10 行,它会返回 10 行然后停止运行。 This thread 进一步解释

以上是关于它是如何工作的? - 查询中的多个子选择的主要内容,如果未能解决你的问题,请参考以下文章

选择语句中的子查询如何在 oracle 中工作

基于查询的子表单中的字段的 Access 2007 验证帮助

模型中1个函数中的多个MySQL查询

从多个表中创建 Sql Server VIEW GROUPing BY,选择子查询作为别名

无法深入访问字段多个子查询

如何在子查询的 WHERE 子句中使用来自 UNNEST 的多个值?