因此,我有一个函数可以返回一些我想在我的网站上实现分页的记录。 有人建议我使用 SQL Server 2012 中的 Offset/Fetch Next 来完成此操作。 在我们的网站上,我们有一个区域列出了记录总数以及您当时所在的页面。
之前,我获取了整个记录集,并能够以编程方式在此基础上构建分页。 但是使用仅 FETCH NEXT X ROWS 的 SQL 方式,我只返回 X 行,所以我不知道我的总记录集是什么以及如何计算我的最小和最大页数。 我能告诉您执行此操作的唯一方法是调用该函数两次并在第一次上执行行计数,然后使用 FETCH NEXT 运行第二次。 有没有更好的方法,不会让我运行查询两次? 我正在努力提高性能,而不是降低性能。
我在使用 COUNT() OVER() 方法时遇到了一些性能问题。 (我不确定是否是服务器的问题,因为它花了 40 秒返回 10 条记录,然后没有任何问题。)这种技术在所有条件下都有效,无需使用 COUNT() OVER() 并完成同样的事情:
DECLARE
@PageSize INT = 10,
@PageNum INT = 1;
WITH TempResult AS(
SELECT ID, Name
FROM Table
), TempCount AS (
SELECT COUNT(*) AS MaxRows FROM TempResult
)
SELECT *
FROM TempResult, TempCount
ORDER BY TempResult.Name
OFFSET (@PageNum-1)*@PageSize ROWS
FETCH NEXT @PageSize ROWS ONLY
您可以使用
COUNT(*) OVER()
...这是一个使用 sys.all_objects
的快速示例:
DECLARE
@PageSize INT = 10,
@PageNum INT = 1;
SELECT
name, object_id,
overall_count = COUNT(*) OVER()
FROM sys.all_objects
ORDER BY name
OFFSET (@PageNum-1)*@PageSize ROWS
FETCH NEXT @PageSize ROWS ONLY;
但是,这应该保留用于小数据集;在较大的集合上,性能可能会很糟糕。 请参阅这篇 Paul White 文章以获得更好的替代方案,包括维护索引视图(仅在结果未经过滤或您提前知道
WHERE
子句时才有效)和使用 ROW_NUMBER()
技巧。
显然,根据查询的不同,结果可能会有很大差异。我用以下结果测试了我的案例:(8 个连接,2 个子查询,5800 行不同结果,5900 行非不同):
COUNT(1) OVER()
~0.820 秒(Aaron Bertrand 的答案,但结果错误*)
#TEMP
表格。WITH .. AS
(James Moberg 的回答)*就我而言,Aaron Bertrand's的答案不起作用,因为
COUNT(1) OVER()
似乎包含由DISTINCT
过滤掉的行。
使用临时表:
DECLARE
@PageSize INT = 10,
@PageNum INT = 1;
SELECT
name, object_id
INTO #MY_TEMP
FROM sys.all_objects
SELECT *
FROM #MY_TEMP
ORDER BY name
OFFSET (@PageNum-1)*@PageSize ROWS
FETCH NEXT @PageSize ROWS ONLY;
SELECT COUNT(1) FROM #MY_TEMP
-- or
-- SELECT @MY_OUTPUT_PARAM = COUNT(1) FROM #MY_TEMP
DROP TABLE #MY_TEMP
临时表的好处是可以将计数分成不同的结果或输出参数。
基于 James Moberg 的回答:
这是使用
Row_Number()
的替代方案,如果您没有 SQL Server 2012 并且无法使用 OFFSET
DECLARE
@PageNumEnd INT = 10,
@PageNum INT = 1;
WITH TempResult AS(
SELECT ID, NAME
FROM Tabla
), TempCount AS (
SELECT COUNT(*) AS MaxRows FROM TempResult
)
select *
from
(
SELECT
ROW_NUMBER() OVER ( ORDER BY PolizaId DESC) AS 'NumeroRenglon',
MaxRows,
ID,
Name
FROM TempResult, TempCount
)resultados
WHERE NumeroRenglon >= @PageNum
AND NumeroRenglon <= @PageNumEnd
ORDER BY NumeroRenglon