我有两个具有以下架构的表:
Table A
:ColumnA, UserId,
... - 为了简洁,省略了架构的其余部分Table B
:ColumnB, UserId,
... - 为了简洁,省略了架构的其余部分表之间可以有重复的值。例如 - 表 A 行
(<some-columnA-value>, 1, ...)
和表 B 行 (<some-columnB-value>, 1, ...)
,1 是 UserId。
现在,我有一个 API,用于从两个表中获取所有
UserId
值。随着数据的增加,我现在想为此 API 使用分页,并希望相应地修改查询。页面之间或页面内也不应该有任何重复项。
我如何实现这一目标?还有一个要求是我需要使用键集分页而不是偏移分页,因为当偏移量增加时,偏移分页会变得更慢。
到目前为止,我已经考虑过使用索引视图,因为我只需要获取 1 列,但由于数据不断频繁且大量地变化,维护索引视图的开销并不是最佳的。
表A:
A 栏 | 用户ID |
---|---|
x | 1 |
y | 2 |
z | 3 |
w | 4 |
表B:
B 栏 | 用户ID |
---|---|
a | 1 |
b | 3 |
c | 5 |
d | 6 |
结果(如果没有页面尺寸):
用户ID |
---|
1 |
2 |
3 |
4 |
5 |
6 |
结果(如果页面大小为 3)
第 1 页
用户ID |
---|
1 |
2 |
3 |
第2页
用户ID |
---|
4 |
5 |
6 |
正如我在我关于 Keyset Pagination(按键分页)的规范帖子中提到的,基本查询需要高效。
您的情况的关键(原文如此)是使用合并并,然后在过滤到前 3 个之后对该集合进行区分。
所以首先UNION ALL
将表格放在一起,然后取前3名(包括平局),然后
DISTINCT
最终结果。
WITH Unioned AS (
SELECT a.UserId
FROM TableA a
UNION ALL
SELECT b.UserId
FROM TableB b
),
Topped AS (
SELECT TOP (3) WITH TIES
t.UserId
FROM Unioned t
ORDER BY UserId
)
SELECT DISTINCT
t.UserId
FROM Topped t;
最终的查询计划漂亮整洁。正如我提到的,您需要保留之前的最高 ID 值,并将其传递给下一个查询。将其放在
TOP
部分,编译器通常会将其下推到较低级别。如果您愿意,您可以将其放入联盟的两半中。
WITH Unioned AS (
SELECT a.UserId
FROM TableA a
UNION ALL
SELECT b.UserId
FROM TableB b
),
Topped AS (
SELECT TOP (3) WITH TIES
t.UserId
FROM Unioned t
WHERE t.UserId = @previousId
ORDER BY UserId
)
SELECT DISTINCT
t.UserId
FROM Topped t;