问:我如何处理类似上传用户名称的字符串?
A:与处理日期和数字的方式相同。字符串也是“可订购的”。
问:如何处理排序列中下一项具有相同值的情况?
答:与处理非唯一日期的重复值的方式相同。除了“主要”排序列之外,您还需要另一个独特的“次要”排序列,或者“主要”和“次要”组合在一起是唯一的。
理想情况下,您可以在非可空列上使用PRIMARY KEY或UNIQUE KEY作为“次要”排序顺序。
“技巧”是保存列表中的当前位置,方法是将“最后看到的”行保存为主要值和次要值,然后在查询中使用该信息以获取“下一页”。
WHERE t.major >= :last_seen_major
AND (t.major > :last_seen_major OR t.minor > :last_seen_minor)
ORDER BY t.major ASC, t.minor ASC
LIMIT 1
从最后一行(在这种情况下,只有一行),您需要保存主列和次列的值,以便可以在同一查询中使用这些值以获取“下一行”。
为了获得最佳查询效果,您需要一个可用前导列为(major, minor)的索引。
根据您的查询,假设您有id列,您可以执行以下操作:
SELECT f.*
FROM Files f
WHERE f.date >= :last_seen_date
AND (f.date > :last_seen_date OR f.id > :last_seen_id)
ORDER BY f.date ASC, f.id ASC
LIMIT 1
要按其他列排序,请将WHERE和ORDER BY子句中的f.date替换为其他内容,例如: f.name。
性能较差的替代
另一种非常流行的方法是在LIMIT子句中使用“offset”。
乍一看,这似乎是一个优雅的解决方案,但它确实有一些麻烦。
你可以这样做:
ORDER BY major ASC, minor ASC LIMIT 41,1
对于“下一行”,您将偏移量增加1
ORDER BY major ASC, minor ASC LIMIT 42,1
此方法存在一个问题,如果在已经看到的行范围内插入行,则“下一个”查询将返回相同的行。因为第41行现在是第42行。如果有人删除了一行,“下一个”查询将跳过一行。而且我不愿意在我的“获得下一行”功能中遇到这种缺陷。这种方法仍然需要跟踪列表中的位置,但是通过携带额外的偏移量而不是行的一部分。
这种方法的另一个问题是数据库必须检索行,然后对它们进行排序,然后最后应用LIMIT子句,这可能是大型集的性能问题。