将任意SQL SELECT TOP(x)转换为SELECT COUNT(*)?

将任意SQL SELECT TOP(x)转换为SELECT COUNT(*)?,sql,algorithm,count,Sql,Algorithm,Count,我希望能够接受任何通常会返回大量行(没有X限制)的任意SELECT TOP(X)查询,并将该查询转换为计算在没有TOP(X)的情况下返回多少行的查询(即SELECT COUNT(*))。记住,我问的是一个任意查询,包含任意数量的连接、where子句、group by等 有办法做到这一点吗 编辑以显示Shannon解决方案的语法: i、 e 变成 `SELECT COUNT(*) FROM (SELECT [colnames] FROM [tables with joins] WHERE

我希望能够接受任何通常会返回大量行(没有X限制)的任意
SELECT TOP(X)
查询,并将该查询转换为计算在没有
TOP(X)
的情况下返回多少行的查询(即
SELECT COUNT(*)
)。记住,我问的是一个任意查询,包含任意数量的连接、where子句、group by等

有办法做到这一点吗


编辑以显示Shannon解决方案的语法:

i、 e

变成

`SELECT COUNT(*) FROM 
 (SELECT [colnames] FROM [tables with joins] 
 WHERE [constraints] GROUP BY [cols]) t`
内联视图:

select count(*)
from (...slightly transformed query...) t
。。。稍微变形的查询。。。是:

  • 如果
    select
    子句包含任何没有名称的列,例如
    select。。。avg(x).
    然后执行以下操作之一:1)将列别名,例如
    avg(x)作为AvgX
    ,2)删除列,但确保至少留下一列,或我最喜欢的3)只需将select子句
    选择1作为C
  • select
    子句中删除
    TOP
  • 删除
    orderby
    子句
  • EDIT 1通过为内联视图添加别名并在
    select
    子句中处理未命名列来修复此问题


    编辑2但性能如何?这难道不需要数据库运行我想首先用TOP(X)避免的大查询吗

    不一定。对于某些查询,可能会出现这样的情况,即此计数将比顶部(x)做更多的工作。在这种情况下,对于特定的查询,您可以通过进行额外的更改来删除最终计数不需要的工作,从而加快等效计数。但是,这些简化不能包含在常规方法中,以执行任何通常会返回大量行(没有X限制)的任意SELECT TOP(X)查询,并将该查询转换为计算没有TOP(X)时返回多少行的查询

    在某些情况下,查询优化器可能会优化掉一些东西,这样数据库就不会运行大型查询

    例如使用SQL Server 2005测试表和数据:

    create table t (PK int identity(1, 1) primary key,
      u int not null unique,
      string VARCHAR(2000))
    
    insert into t (u, string)
    select top 100000 row_number() over (order by s1.id) , replace(space(2000), ' ', 'x')
    from sysobjects s1, 
        sysobjects s2, 
        sysobjects s3, 
        sysobjects s4, 
        sysobjects s5, 
        sysobjects s6, 
        sysobjects s7
    
    u
    上的非聚集索引将比列
    PK
    上的聚集索引小得多

    然后设置SMS以显示以下各项的实际执行计划:

    select PK, U, String from t
    select count(*) from t
    
    第一个select执行集群索引扫描,因为它需要从leaf中返回数据。第二个查询对为U上的唯一约束创建的较小的非集群索引进行索引扫描

    应用我们得到的第一个查询的转换:

    select count(*)
    from (select PK, U, String from t) t
    

    运行该程序并查看计划,再次使用U上的索引,与t中的
    选择计数(*)完全相同。不会访问叶子来查找每一行上字符串的值。

    但是问题中提到的GROUP BY问题呢?GROUP BY可以位于FROM(…)范围内的查询。mssql在最后一行给出了此查询的语法错误。)有什么想法吗?不确定这是否是您的问题,但有时内部查询需要别名。尝试从(旧查询)t中选择计数(*),但性能如何?这难道不需要数据库运行我想用TOP(X)首先避免的大查询吗
    select count(*)
    from (select PK, U, String from t) t