【问题标题】:Get total row count while paging分页时获取总行数
【发布时间】:2013-10-01 20:32:18
【问题描述】:

我有一个搜索屏幕,用户可以在其中搜索 5 个过滤器。
我基于这些过滤器值构建了一个动态查询,并且一次生成了第 10 页的结果。
这在使用 OFFSETFETCH 的 SQL2012 中运行良好,但我使用 两个 查询来执行此操作。

我想显示 10 个结果显示查询找到的总行数(比如说 1000)。
目前,我通过运行查询 两次 来执行此操作 - 一次用于总计数,然后再次对 10 行进行分页。
有没有更有效的方法来做到这一点?

【问题讨论】:

    标签: sql sql-server sql-server-2012 paging fetch


    【解决方案1】:

    您不必运行两次查询。

    SELECT ..., total_count = COUNT(*) OVER()
    FROM ...
    ORDER BY ...
    OFFSET 120 ROWS
    FETCH NEXT 10 ROWS ONLY;
    

    基于the chat,您的问题似乎有点复杂 - 除了分页之外,您还将DISTINCT 应用于结果。这会使确定COUNT() 应该是什么样子以及应该去哪里变得复杂。这是一种方法(我只是想证明这一点,而不是尝试将该技术纳入您从聊天中获得的更复杂的查询中):

    USE tempdb;
    GO
    CREATE TABLE dbo.PagingSample(id INT,name SYSNAME);
    
    -- insert 20 rows, 10 x 2 duplicates
    INSERT dbo.PagingSample SELECT TOP (10) [object_id], name FROM sys.all_columns;
    INSERT dbo.PagingSample SELECT TOP (10) [object_id], name FROM sys.all_columns;
    
    SELECT COUNT(*) FROM dbo.PagingSample; -- 20
    
    SELECT COUNT(*) FROM (SELECT DISTINCT id, name FROM dbo.PagingSample) AS x; -- 10
    
    SELECT DISTINCT id, name FROM dbo.PagingSample; -- 10 rows
    
    SELECT DISTINCT id, name, COUNT(*) OVER() -- 20 (DISTINCT is not computed yet)
     FROM dbo.PagingSample
     ORDER BY id, name
     OFFSET (0) ROWS FETCH NEXT (5) ROWS ONLY; -- 5 rows
    
    -- this returns 5 rows but shows the pre- and post-distinct counts:
    SELECT PostDistinctCount = COUNT(*) OVER() -- 10, 
      PreDistinctCount -- 20, 
      id, name 
    FROM 
    (
      SELECT DISTINCT id, name, PreDistinctCount = COUNT(*) OVER() 
        FROM dbo.PagingSample
        -- INNER JOIN ...
    ) AS x
    ORDER BY id, name
    OFFSET (0) ROWS FETCH NEXT (5) ROWS ONLY;
    

    清理:

    DROP TABLE dbo.PagingSample;
    GO
    

    【讨论】:

    • 如果我将变量名指定为@oTotalRecords = COUNT(1) OVER(),这仅在动态查询中起作用,它表示“必须声明标量变量“@oTotalRecords”。可以请告诉我如何解决它。
    • 我正在将值读入一个变量并从应用程序中读取。
    • 我可以从sql本身把它变成一个变量吗??
    • 我还有其他方法可以做到吗?
    • 非常感谢好友...你真是太棒了
    【解决方案2】:

    我的解决方案类似于“rs. answer”

    DECLARE @PageNumber AS INT, @RowspPage AS INT
    SET @PageNumber = 2
    SET @RowspPage = 5 
    
    SELECT   COUNT(*) OVER() totalrow_count,*
        FROM databasename
        where columnname like '%abc%'
        ORDER BY columnname
        OFFSET ((@PageNumber - 1) * @RowspPage) ROWS
        FETCH NEXT @RowspPage ROWS ONLY;
    

    返回结果将包含 totalrow_count 作为第一列名

    【讨论】:

      【解决方案3】:

      你能试试这样的吗

      SELECT TOP 10 * FROM 
      (
         SELECT COUNT(*) OVER() TOTALCNT, T.*
         FROM TABLE1 T
         WHERE col1 = 'somefilter'
      ) v
      

      SELECT * FROM 
      (
         SELECT COUNT(*) OVER() TOTALCNT, T.*
         FROM TABLE1 T
         WHERE col1 = 'somefilter'
      ) v
      ORDER BY COL1
      OFFSET 0 ROWS FETCH FIRST 10 ROWS ONLY
      

      现在您的 totalcnt 列中有总数,您可以使用此列显示总行数

      【讨论】:

      • 问题是那里有一个不同的,所以它的逻辑有点复杂。在同一级别,COUNT() OVER() 将在 DISTINCT 之前计算。
      【解决方案4】:

      在我使用复杂连接并返回约 6,000 条记录的测试中,执行两个单独的查询要快得多。更快,以毫秒为单位获取总数并分别返回 100 条记录的子集,而执行组合查询需要 17 秒。其他人看到这种性能冲击吗?显然,它可能与数据结构有关,但这仍然是一个巨大的差异。

      【讨论】:

        【解决方案5】:

        我希望我现在回答这个问题还不算太晚,但今晚我遇到了一个非常相似的问题。我有一个分页类过度夸大了返回的结果数量,因为之前的开发人员正在删除 DISTINCT 并且只是执行表连接的 SELECT count(*)。虽然这并不能解决 2 查询问题,但我最终使用了嵌套查询,因此它看起来像这样:

        原始查询

        SELECT DISTINCT
          field1, field2
        FROM
          table1 t1
          left join table2 t2 on t2.id = t1.id
        

        过度膨胀的结果查询

        SELECT
          count(*)
        FROM
          table1 t1
          left join table2 t2 on t2.id = t1.id
        

        我的结果查询解决方案

        SELECT
          count(*)
        FROM
          (SELECT DISTINCT
             field1, field2
           FROM
             table1 t1
             left join table2 t2 on t2.id = t1.id) as tbl;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-04-04
          • 2013-10-23
          • 1970-01-01
          • 2016-12-03
          • 2023-03-18
          • 1970-01-01
          • 2012-04-07
          • 1970-01-01
          相关资源
          最近更新 更多