分页数据时使用SQL查询获取总记录数的最佳方法

分页数据时使用SQL查询获取总记录数的最佳方法,sql,sql-server-2012,paging,fetch,offset,Sql,Sql Server 2012,Paging,Fetch,Offset,我在一个每页可容纳15行的页面上显示数据。我正在使用SQL Server 2012的OFFSET&FETCH关键字来限制我想要的15行。但是,我想显示可用行的总数,如何在单个查询中显示 例如,在页面顶部,您正在查看1505条记录中的15条 有什么方法可以将其与现有查询结合起来吗?您可以使用COUNT: 然后是每一页的计数,您必须使用您选择的编程语言,例如php或asp.net 基本上计算是这样的: PageNumber * RecordsPerPage $TotalPages = Ceil($

我在一个每页可容纳15行的页面上显示数据。我正在使用SQL Server 2012的OFFSET&FETCH关键字来限制我想要的15行。但是,我想显示可用行的总数,如何在单个查询中显示

例如,在页面顶部,您正在查看1505条记录中的15条

有什么方法可以将其与现有查询结合起来吗?

您可以使用COUNT:

然后是每一页的计数,您必须使用您选择的编程语言,例如php或asp.net

基本上计算是这样的:

PageNumber * RecordsPerPage
$TotalPages = Ceil($NumberOfRecords / $RecordsPerPages)
int TotalPages = Math.Ceil(NumberOfRecords/RecordsPerPages);
WITH resultSet AS     
(
SELECT 
   ROW_NUMBER() OVER(ORDER BY x.ID DESC) as Row, 
   x.other_fields
   FROM Table x    
   WHERE conditions_x
),
cte AS
(
   SELECT TOP 1 Row AS cte_row FROM resultSet ORDER BY Row DESC
)
-- And finally:
SELECT cte.cte_row AS Total, * FROM resultSet CROSS JOIN cte 
WHERE Row BETWEEN 11 AND 20; -- Rows between 11 and 20, for example. Those would be your previously computed START and END row variables.
假设第2页每页有15条记录,则为:

2 * 15
TotalPages = CEILING(1,505 / 15)
因此,您的输出将是

30 of NumberOfRecords
您可以使用公式计算页面的数量

TotalPages = CEILING(TotalRecords / RecordsPerPages)
例如,使用您自己的数字,它将是:

2 * 15
TotalPages = CEILING(1,505 / 15)
这是101,如果你得到了上限值

如果是Php,则可能如下所示:

PageNumber * RecordsPerPage
$TotalPages = Ceil($NumberOfRecords / $RecordsPerPages)
int TotalPages = Math.Ceil(NumberOfRecords/RecordsPerPages);
WITH resultSet AS     
(
SELECT 
   ROW_NUMBER() OVER(ORDER BY x.ID DESC) as Row, 
   x.other_fields
   FROM Table x    
   WHERE conditions_x
),
cte AS
(
   SELECT TOP 1 Row AS cte_row FROM resultSet ORDER BY Row DESC
)
-- And finally:
SELECT cte.cte_row AS Total, * FROM resultSet CROSS JOIN cte 
WHERE Row BETWEEN 11 AND 20; -- Rows between 11 and 20, for example. Those would be your previously computed START and END row variables.
如果ASP使用C,则可能如下所示:

PageNumber * RecordsPerPage
$TotalPages = Ceil($NumberOfRecords / $RecordsPerPages)
int TotalPages = Math.Ceil(NumberOfRecords/RecordsPerPages);
WITH resultSet AS     
(
SELECT 
   ROW_NUMBER() OVER(ORDER BY x.ID DESC) as Row, 
   x.other_fields
   FROM Table x    
   WHERE conditions_x
),
cte AS
(
   SELECT TOP 1 Row AS cte_row FROM resultSet ORDER BY Row DESC
)
-- And finally:
SELECT cte.cte_row AS Total, * FROM resultSet CROSS JOIN cte 
WHERE Row BETWEEN 11 AND 20; -- Rows between 11 and 20, for example. Those would be your previously computed START and END row variables.
但是,如果他们单击最后一页,则您可以简单地放置:

TotalRecords of TotalRecords
例如:

1,505 of 1,505

正如其他人所演示的,您可以做到这一点,但我将利用系统metatdata,这比他们演示的使用COUNT快得多。从物理上讲,从MyTable中调用SELECT COUNT1 AS rc将强制存储引擎枚举内存中可能存在或不存在的所有数据,以执行计数并等待任何独占锁解锁

你知道什么更有效率吗?只看sys.allocation\u单位

SELECT
    s.[Name] as [Schema] 
,   t.[name] as [Table] 
,   SUM(p.rows) as [RowCount] 
FROM
    sys.schemas s 
    LEFT OUTER JOIN 
        sys.tables t 
        ON s.schema_id = t.schema_id 
    LEFT OUTER JOIN 
        sys.partitions p 
        ON t.object_id = p.object_id 
    LEFT OUTER JOIN  
        sys.allocation_units a 
        ON p.partition_id = a.container_id 
WHERE
    p.index_id  in(0,1) -- 0 heap table , 1 table with clustered index 
    AND p.rows is not null
    AND a.type = 1  -- row-data only , not LOB 
GROUP BY 
    s.[Name] 
,   t.[name] 
ORDER BY 
    1 
,   2; 
h/t至bimonkey,以获得其职位

如果您想要一个单独的查询来实现这一点,那么您需要将上述内容与偏移量和提取结合起来

在SQL中,不要被将更少的代码行等同于更低的复杂性或更好的性能所愚弄

我对以下查询进行了注释,因为它非常简单

-- Create variables for our usage
-- http://technet.microsoft.com/en-us/library/ms188927.aspx
DECLARE @OFFSET int = 30
,   @FETCH int = 15;

-- Notice the previous statement ends with a semicolon (;)
-- The following structure is a Common Table Expression (CTE)
-- Think of it as a single use View
-- http://technet.microsoft.com/en-us/library/ms190766(v=sql.105).aspx
WITH COUNTS AS
(
    -- This query provides the number of rows in all the tables
    -- in the current catalog. It is screaming cheetah wheelies fast 
    -- as it does not need to physically read each row from each table
    -- to generate counts. Instead, it is using system metadata to 
    -- derive the row count.
    -- After the closing ), I will have access to a tabular structure
    -- called COUNTS 
    SELECT
        s.[Name] as [Schema] 
    ,   t.[name] as [Table] 
    ,   SUM(p.rows) as [RowCount] 
    FROM
        -- http://technet.microsoft.com/en-us/library/ms176011.aspx
        sys.schemas s 
        LEFT OUTER JOIN 
            -- http://technet.microsoft.com/en-us/library/ms187406.aspx
            sys.tables t 
            ON s.schema_id = t.schema_id 
        LEFT OUTER JOIN 
            -- http://technet.microsoft.com/en-us/library/ms175012.aspx
            sys.partitions p 
            ON t.object_id = p.object_id 
        LEFT OUTER JOIN  
            -- http://technet.microsoft.com/en-us/library/ms189792.aspx
            sys.allocation_units a 
            ON p.partition_id = a.container_id 
    WHERE
        p.index_id  in(0,1) -- 0 heap table , 1 table with clustered index 
        AND p.rows is not null
        AND a.type = 1  -- row-data only , not LOB 
    GROUP BY 
        s.[Name] 
    ,   t.[name] 
)
SELECT
    T.*
,   @OFFSET AS StartingRow
,   @FETCH AS PageSize
-- A subquery that uses the CTE above to extract our table's total row count
-- The table and schema below must align with the value in your FROM clause
-- http://technet.microsoft.com/en-us/library/ms189575(v=sql.105).aspx
,   (SELECT C.[RowCount] FROM COUNTS C WHERE C.[schema] = 'dbo' AND C.[Table] = 'MyTable') AS TotalRows
FROM
    dbo.MyTable T
ORDER BY
    1
-- http://technet.microsoft.com/en-us/library/gg699618.aspx    
OFFSET 30 ROWS
FETCH NEXT 15 ROWS ONLY;

对于使用SQLServer10.50的用户,我可以通过公共表表达式CTE使用结果集。大概是这样的:

PageNumber * RecordsPerPage
$TotalPages = Ceil($NumberOfRecords / $RecordsPerPages)
int TotalPages = Math.Ceil(NumberOfRecords/RecordsPerPages);
WITH resultSet AS     
(
SELECT 
   ROW_NUMBER() OVER(ORDER BY x.ID DESC) as Row, 
   x.other_fields
   FROM Table x    
   WHERE conditions_x
),
cte AS
(
   SELECT TOP 1 Row AS cte_row FROM resultSet ORDER BY Row DESC
)
-- And finally:
SELECT cte.cte_row AS Total, * FROM resultSet CROSS JOIN cte 
WHERE Row BETWEEN 11 AND 20; -- Rows between 11 and 20, for example. Those would be your previously computed START and END row variables.
这应该作为一个查询执行


虽然我没有在SQL server 2012中尝试过这一点,但我认为它可能也会起作用。

我通过使用SQLDataReader并查询两个单独的表解决了这一特殊情况。一个表包含15条记录,然后另一个查询使用Count函数调用总记录。谢谢你的建议,你的查询让我有点吃惊,所以我选择了Count方法,但很高兴知道有一种更有效的方法,在我真正需要的时候代替Count。