目前我们执行两个查询以使用分页过滤器获取计数和结果。虽然我们可以轻松地将这两者结合到一个网络调用中(使用 sql 分隔符),但有没有办法在遵循DRY原则的单个查询中做到这一点?
-- count
SELECT COUNT(*) FROM table;
-- result with pagination
SELECT *
FROM (SELECT ROW_NUMBER() OVER (ORDER BY tbl.idn) AS row, * FROM tbl)_tbl
WHERE row >= 1 AND row <= 10;
Run Code Online (Sandbox Code Playgroud)
维护两个查询真的很有挑战性——单个查询减少了维护开销。
您可以尝试创建一个存储过程并从应用程序中调用它。
CREATE PROCEDURE [dbo].[getPage]
AS
BEGIN
DECLARE @cnt INT = (SELECT COUNT(*) FROM table)
SELECT *, [cnt] = @cnt
FROM (SELECT ROW_NUMBER() OVER (ORDER BY tbl.idn) AS row, * FROM tbl)_tbl
WHERE row >= 1 AND row <= 10;
END
Run Code Online (Sandbox Code Playgroud)
或者您可以使用子查询:
CREATE PROCEDURE [dbo].[getPage]
AS
BEGIN
SELECT *, [cnt] = (SELECT COUNT(*) FROM table)
FROM (SELECT ROW_NUMBER() OVER (ORDER BY tbl.idn) AS row, * FROM tbl)_tbl
WHERE row >= 1 AND row <= 10;
END
Run Code Online (Sandbox Code Playgroud)
编辑。
更好的是,您可以使用OFFSET FETCH
子句进行分页目的。您将获得更清晰的代码和更高的性能(此处没有窗口函数)。例如像这样的东西:
CREATE PROCEDURE [dbo].[getPage]
AS
BEGIN
DECLARE @cnt INT = (SELECT COUNT(*) FROM table)
SELECT *, [cnt] = @cnt
FROM tbl
ORDER BY idn
OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;
END
Run Code Online (Sandbox Code Playgroud)
或者使用子查询:
CREATE PROCEDURE [dbo].[getPage]
AS
BEGIN
SELECT *, [cnt] = (SELECT COUNT(*) FROM table)
FROM tbl
ORDER BY idn
OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;
END
Run Code Online (Sandbox Code Playgroud)
子查询和变量方法之间没有显着差异。更多的是关于符号。SQL Server 做几乎相同的工作(额外的“无成本”嵌套循环)。在这种特殊情况下,我更喜欢避免窗口函数(可能的 Table Spool - 对 tempdb 的额外影响)。
归档时间: |
|
查看次数: |
3134 次 |
最近记录: |