为什么要使用“选择前100%”?


82

我知道在SQL Server 2005之前,您可以“欺骗” SQL Server,以允许在视图定义中使用订单,也可以TOP 100 PERCENTSELECT子句中包含该订单。但是我看到了我继承的其他代码,这些代码SELECT TOP 100 PERCENT在动态SQL语句(在ASP.NET应用程序的ADO中 使用)中使用了...。有什么理由吗?结果与包括一样吗?TOP 100 PERCENT


5
也许正在进行一些语句构建:“ SELECT TOP {0} PERCENT ...”
Michael Petrotta,2009年

您的第一句话已成为我隐藏的问题之一。
穆罕默德·阿希库扎曼

我使用顶部的99.9999999 PERCENT,它始终有效。已经足够近了。我倾向于根据预期的记录数添加数字“ 9”。更多记录,更多9,它总是有效。我已经跨越2008 SQL用于SQL 2017
儿科

Answers:


51

它用于“中间实现(Google搜索)

好文章:Adam Machanic:探索中间实现的秘密

他甚至提出了MS Connect,因此可以以更清洁的方式完成

我的观点“并非天生不好”,但除非100%确信,否则不要使用它。问题是,它仅在您执行操作时才起作用,并且可能以后不会起作用(补丁程序级别,架构,索引,行数等)...

工作的例子

这可能会失败,因为您不知道事物的评估顺序

SELECT foo From MyTable WHERE ISNUMERIC (foo) = 1 AND CAST(foo AS int) > 100

而且这也可能失败,因为

SELECT foo
FROM
    (SELECT foo From MyTable WHERE ISNUMERIC (foo) = 1) bar
WHERE
    CAST(foo AS int) > 100

但是,这在SQL Server 2000中没有。内部查询被评估并假脱机:

SELECT foo
FROM
    (SELECT TOP 100 PERCENT foo From MyTable WHERE ISNUMERIC (foo) = 1 ORDER BY foo) bar
WHERE
    CAST(foo AS int) > 100

请注意,这在SQL Server 2005中仍然有效

SELECT TOP 2000000000 ... ORDER BY...

为什么第二个查询失败?因为内部查询没有(必须)得到充分评估?
肯尼·埃维特

第二个链接说明了为什么创建临时表有时会显着提高性能!
肯尼·埃维特

41

TOP(100)PERCENT在SQL Server的最新版本中完全没有意义,并且它(以及相应的ORDER BY,在视图定义或派生表的情况下)将被查询处理器忽略。

您是对的,曾经有一段时间,它可以用作技巧,但即使如此,它也不可靠。可悲的是,Microsoft的某些图形工具加入了这个毫无意义的条款。

至于为什么它可能会出现在动态SQL中,我不知道。您是正确的,没有理由,没有它的结果是相同的(同样,对于视图定义或派生表,没有TOP和ORDER BY子句)。


这不是真的。有关详细信息,请参见@gbn的答案中的此链接
肯尼·埃维特

3
您引用的链接没有提到SELECT TOP(100)PERCENT .. ORDER BY,这毫无意义。该链接提到了SELECT TOP(2147483647).. ORDER BY的使用。当前,SQL Server优化器将消除SELECT TOP(100)PERCENT .. ORDER BY,因为它没有意义。这种组合总是定义与SELECT相同的行集合,而没有TOP / ORDER BY。优化器当前不尝试确定2147483647是否包含所有行,因此在这种情况下不会消除TOP-ORDER BY组合。
史蒂夫·卡斯

2
该链接实际上确实提到TOP (100) PERCENT:“ ...我可能会尝试通过将TOP 100 PERCENT与ORDER BY结合使用来强制派生表的中间实现(没有临时表)。不幸的是,SQL Server查询优化器团队认为这不是。并不是一个好主意,优化器现在忽略了这种尝试。” 它实际上支持您。
肯尼·埃维特

如果可以的话,我将撤消我的反对票。[如果您编辑答案,我会对其进行
投票

1
你可能很困惑,因为我改变了主意。我的第一句话是错误的;你是对的。
肯尼·埃维特

23

...允许在视图定义中使用ORDER BY。

那不是一个好主意。视图绝对不应定义ORDER BY。

ORDER BY对性能有影响-使用它的视图意味着ORDER BY将出现在解释计划中。如果您有一个查询,该查询将视图与即时查询中的任何内容连接在一起,或在嵌入式视图中引用(CTE /子查询分解),则ORDER BY始终在最终的ORDER BY之前运行(假定已定义)。当查询未使用TOP(对于MySQL / Postgres为LIMIT)时,对不是最终结果集的行进行排序没有任何好处。

考虑:

CREATE VIEW my_view AS
    SELECT i.item_id,
           i.item_description,
           it.item_type_description
      FROM ITEMS i
      JOIN ITEM_TYPES it ON it.item_type_id = i.item_type_id
  ORDER BY i.item_description

...

  SELECT t.item_id,
         t.item_description,
         t.item_type_description
    FROM my_view t
ORDER BY t.item_type_description

...相当于使用:

  SELECT t.item_id,
         t.item_description,
         t.item_type_description
    FROM (SELECT i.item_id,
                 i.item_description,
                 it.item_type_description
            FROM ITEMS i
            JOIN ITEM_TYPES it ON it.item_type_id = i.item_type_id
        ORDER BY i.item_description) t
ORDER BY t.item_type_description

这很不好,因为:

  1. 该示例首先按商品描述对列表进行排序,然后根据商品类型描述对列表进行重新排序。第一类是浪费资源-按原样运行并不意味着它在运行:ORDER BY item_type_description, item_description
  2. 由于封装原因,对视图的排序方式并不明显。这并不意味着您应该创建具有不同排序顺序的多个视图...

6

如果没有ORDER BY子句,则TOP 100 PERCENT是多余的。(正如您提到的,这是带有视图的“技巧”)

[希望优化器可以优化它。]


5

我看到了我继承的其他代码,这些代码使用SELECT TOP 100 PERCENT

原因很简单:企业管理器曾经试图提供帮助,并格式化您的代码以为您提供帮助。尝试删除它毫无意义,因为它并没有真正伤害到任何东西,下次您进行更改时,EM会再次插入它。


4

我想,除了冷漠外,没有其他原因。

此类查询字符串通常由图形查询工具生成。用户联接一些表,添加过滤器,排序顺序并测试结果。由于用户可能希望将查询另存为视图,因此该工具添加了TOP 100 PERCENT。但是,在这种情况下,用户将SQL复制到他的代码中,参数化了WHERE子句,并将所有内容隐藏在数据访问层中。失去理智,看不见。


1

请尝试以下,希望它对您有用。

      SELECT TOP
              ( SELECT COUNT(foo) 
                  From MyTable 
                 WHERE ISNUMERIC (foo) = 1) * 
                  FROM bar WITH(NOLOCK) 
              ORDER BY foo
                 WHERE CAST(foo AS int) > 100
               )

1

错误说明了一切...

消息1033,级别15,状态1,过程TestView,第5行除非还指定了TOP,OFFSET或FOR XML,否则ORDER BY子句在视图,内联函数,派生表,子查询和公用表表达式中无效。

不要使用TOP 100 PERCENT,请使用TOP n,其中N是数字

SQL Server VIEW(2012年后的版本)忽略了TOP 100 PERCENT(出于我不知道的原因),但我认为MS出于语法原因保留了它。TOP n更好,可以在视图内部工作,并在最初使用视图时以所需的方式对其进行排序,但要小心


0

我想您可以在结果中使用变量,但是除了在视图中获得ORDER BY片段外,通过隐式声明“ TOP 100 PERCENT”不会带来任何好处:

declare @t int
set @t=100
select top (@t) percent * from tableOf

2
问题Why use Select Top 100 Percent不是要获取百分比的可变计数。
bummi 2014年

0

只需尝试一下,它本身就可以解释它。您不能使用ORDER BY创建视图,除非...

CREATE VIEW v_Test
         AS
           SELECT name
             FROM sysobjects
         ORDER BY name
        GO

消息1033,级别15,状态1,过程TestView,第5行除非还指定了TOP,OFFSET或FOR XML,否则ORDER BY子句在视图,内联函数,派生表,子查询和公用表表达式中无效。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.