所以,我有一个函数可以返回一些我希望在我的网站上实现分页的记录。有人建议我使用SQL Server 2012中的Offset / Fetch Next来完成此任务。在我们的网站上,我们有一个区域列出了记录的总数以及您当时所在的页面。
之前,我正在获取整个记录集,并能够以编程方式构建分页。但是只使用带有FETCH NEXT X ROWS的SQL方法,我只返回X行,所以我不知道我的总记录集是什么以及如何计算我的最小和最大页面。我能告诉你这样做的唯一方法是调用函数两次并在第一次执行行计数,然后使用FETCH NEXT运行第二行。有没有更好的方法不让我运行查询两次?我试图加快性能,而不是减慢速度。
答案 0 :(得分:120)
我使用COUNT()OVER()方法遇到了一些性能问题。 (我不确定它是否是服务器,因为它返回10条记录需要40秒,后来没有任何问题。)这种技术在所有条件下都能正常运行,而不必使用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
答案 1 :(得分:94)
您可以使用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;
答案 2 :(得分:2)
显然,结果可能因查询而异。我用以下结果测试了我的案例:(8 个连接,2 个子查询,不同结果中的 5800 行,5900 非不同):
COUNT(1) OVER()
(Aaron Bertrand's answer,但结果错误*)#TEMP
表。WITH .. AS
(James Moberg's anser)*在我的例子中,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
临时表的好处是可以将计数分成不同的结果或输出参数。
答案 3 :(得分:1)
这是使用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