sql-server - SQL Server 中两个表的分页

标签 sql-server t-sql indexing pagination keyset-pagination

我有两个具有以下架构的表:

  • Table A :ColumnA, UserId, ... - 为简洁起见,省略了架构的其余部分
  • Table B :ColumnB, UserId, ... - 为简洁起见,省略了架构的其余部分

表之间可以有重复的值。例如 - 表 A 行 (<some-columnA-value>, 1, ...)和表 B 行 (<some-columnB-value>, 1, ...) , 1 是 UserId。

现在,我有一个 API,用于获取所有 UserId两个表中的值。随着数据的增加,我现在想为此 API 使用分页,并希望相应地修改查询。页面之间或页面内也不应该有任何重复项。

我该如何实现这一目标?还有一个要求是我需要使用键集分页而不是偏移分页,因为当偏移量增加时,偏移分页会变慢。

到目前为止,我已经考虑过使用索引 View ,因为我只需要获取 1 列,但由于数据不断频繁且大量地变化,维护索引 View 的开销并不是最佳的。

表A:

<表类=“s-表”> <标题> A 列 用户ID <正文> x 1 y 2 z 3 w 4

表B:

<表类=“s-表”> <标题> B 列 用户ID <正文> 一个 1 b 3 c 5 d 6

结果(如果没有页面大小):

<表类=“s-表”> <标题> 用户ID <正文> 1 2 3 4 5 6

结果(如果页面大小为 3)

第 1 页

<表类=“s-表”> <标题> 用户ID <正文> 1 2 3

第 2 页

<表类=“s-表”> <标题> 用户ID <正文> 4 5 6

最佳答案

正如我在 my canonical post on Keyset Pagination 中提到的(按键分页),基础查询需要高效。

在你的例子中,关键(原文如此)是使用合并联盟,按ID分组,然后取前3个。这意味着分组是在已经排序的集合上进行的,并且可以使用流聚合

因此,首先将表UNION ALL组合在一起,然后GROUP BY UserId最终结果并取TOP (3)

SELECT TOP (3)
  t.UserId
FROM (
    SELECT a.UserId
    FROM TableA a
    UNION ALL
    SELECT b.UserId
    FROM TableB b
) t
GROUP BY t.UserId
ORDER BY UserId;

最终的查询计划非常漂亮和整洁。请注意,工会在后期阶段保持正确的顺序。

enter image description here

正如我提到的,您需要保留之前的最高 ID 值,并将其传递给下一个查询。将其放入联合体的两半中。

SELECT TOP (3)
  t.UserId
FROM (
    SELECT a.UserId
    FROM TableA a
    WHERE a.UserId > @previousId
    UNION ALL
    SELECT b.UserId
    FROM TableB b
    WHERE b.UserId > @previousId
) t
GROUP BY t.UserId
ORDER BY UserId;

db<>fiddle

关于sql-server - SQL Server 中两个表的分页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77565466/

相关文章:

sql-server - SQL Server 约束是 “not trusted”

mysql - 如何检查MySQL中表字段上是否存在索引

空时间戳上的mysql表索引

sql-server - 无法更改 SSIS 转换脚本编辑器中的值

sql-server - SQL Server 中 To_Char 和 T_Number 交替进行格式化

sql - 具有一对多关系和 orderby 复杂表达式的 Linq SQL 错误

sql-server - SQL : Count Distinct and Combine Similarly-Named

c# - 使用 C# 检索 SQL Server 父/子查询结果

t-sql - Azure SQL Server 中的模糊搜索

Eclipse 索引需要很长时间