【问题标题】:Selecting a number of rows with TOP based on expression根据表达式选择带有 TOP 的行数
【发布时间】:2020-05-16 13:36:40
【问题描述】:

我正在尝试将表格分成两部分。 (SQL Server 2017) 这是我的代码:

 SELECT TOP COUNT(*)/2 TargetColumn
 FROM SomeTable

错误信息是:

'COUNT' 附近的语法不正确

TOP 不允许我这样做。使用固定数字 aka 2000/2 的表达式有效,但上面使用 COUNT 的表达式无效。

我搜索了 StackOverflow,但只找到了相关的 this 帖子,其中有 2 个答案,其中一个被标记为“危险”,第二个我不明白。

【问题讨论】:

    标签: sql sql-server tsql sql-order-by


    【解决方案1】:

    您不能在单个查询中执行此操作,您需要获取行数,然后将其用于您的 top 查询,例如

    DECLARE @NumRows INT;
    
    SELECT @NumRows = COUNT(*)/2
    FROM SomeTable;
    
    SELECT TOP(@NumRows) TargetColumn
    FROM SomeTable;
    

    这是因为TOP 是一个简单的函数,旨在限制返回的行数。必须计算行数需要返回所有行,这是矛盾的。

    如果您希望在单个查询中执行此操作,请参阅@GMB 的回答。

    对于我测试过的桌子,这个解决方案占了 28%,而 GMB 占了 72%,没有订单。如果您通过此解决方案添加订单,则占 52%,而 GMB 占 48%。因此,性能最佳的查询取决于您的具体情况。

    【讨论】:

      【解决方案2】:

      您可以使用窗口函数在单个查询中执行此操作:

      select targetcolumn
      from (
          select 
              targetcolumn, 
              row_number() over(order by somecol) rn,
              count(*) over() cnt
          from sometable
      ) t
      where rn <= cnt / 2
      

      子查询对表中的所有记录执行一个窗口count(),并以row_number() 对记录进行排序。然后,外部查询过滤下半部分。

      请注意,在没有 ORDER BY 子句的情况下使用 TOP 并没有真正的意义:除非明确指定,否则记录的顺序本质上是未定义的,因此这会导致返回未定义的一组行(尽管具有固定数量记录)。我假设您有一个用于订购的列,并在上述查询中将其命名为 somecol

      【讨论】:

      • 嗨,不幸的是我没有让这个工作,在 COUNT 附近得到了关于不正确语法的相同消息。我已经接受了 Dale 的回答,因为他是第一个并且代码有效,所以也许你不会不想调查为什么你的运行不正常。无论如何,感谢您的尝试,非常感谢您的快速回复。
      • @LanaB 在我添加的rn 之后,此答案中缺少一个逗号 (',')。
      猜你喜欢
      • 2012-11-18
      • 2017-06-21
      • 1970-01-01
      • 2015-07-23
      • 2022-08-18
      • 1970-01-01
      • 1970-01-01
      • 2018-11-30
      • 1970-01-01
      相关资源
      最近更新 更多