在单个 SQL 查询中获取两个下一个和两个上一个条目
Posted
技术标签:
【中文标题】在单个 SQL 查询中获取两个下一个和两个上一个条目【英文标题】:Fetch two next and two previous entries in a single SQL query 【发布时间】:2009-01-02 12:09:51 【问题描述】:我想显示一个图片库,并且在视图页面上,应该可以看到一堆缩略图:当前图片,包含前面的两个条目和后面的两个条目。
获取两个下一个/上一个的问题是我不能(除非我弄错了)选择像 MAX(id) WHERE idxx 这样的东西。
有什么想法吗?
注意:当然 id 不跟随,因为它们应该是多个 WHERE 实例的结果。
谢谢 马歇尔
【问题讨论】:
【参考方案1】:请原谅 SQL Server 风格的变量名,我不记得 mysql 是如何进行变量命名的。
SELECT *
FROM photos
WHERE photo_id = @current_photo_id
UNION ALL
SELECT *
FROM photos
WHERE photo_id > @current_photo_id
ORDER BY photo_id ASC
LIMIT 2
UNION ALL
SELECT *
FROM photos
WHERE photo_id < @current_photo_id
ORDER BY photo_id DESC
LIMIT 2;
此查询假定您可能有不连续的 ID。但是,从长远来看,如果您的表中有很多照片,因为经常在从数据库中检索到整个结果集之后评估 TOP,这可能会成为问题。 YMMV。
在高负载情况下,我可能会使用这些查询,但我也会定期预实现它们,以便每张照片都有一个 PreviousPhotoOne、PreviousPhotoTwo 等列。维护起来有点多,但是当你有大量静态数据并且需要性能时,它工作得很好。
【讨论】:
【参考方案2】:如果你的 ID 是连续的,你可以这样做
where id >= @id-2 and id <= @id+2
否则我认为你必须union
3 次查询,一个以获取具有给定 id 的记录,另外两个与 top
和 order by
这样搞乱
select *
from table
where id = @id
union
select top 2 *
from table
where id < @id
order by id desc
union
select top 2 *
from table
where id > @id
order by id
性能不会太差,因为您没有检索大量数据集,但由于使用union
,性能不会很好。
如果您发现性能开始出现问题,您可以添加列来保存上一个和下一个项目的 ID;使用触发器或通宵过程或其他方式计算 id。这意味着您只需执行一次硬查询,而不是每次需要时执行。
【讨论】:
注意:“TOP 2”是专有的 Microsoft/Sybase 语法,MySQL 不支持。相反,MySQL 使用出现在 ORDER BY 子句之后的可选 LIMIT 子句。【参考方案3】:我认为这种方法应该适用于非连续 ID,并且应该比使用 UNION 更有效。 currentID 将使用 SQL 中的常量或从您的程序传递来设置。
SELECT * FROM photos WHERE ID = currentID OR ID IN (
SELECT ID FROM photos WHERE ID < currentID ORDER BY ID DESC LIMIT 2
) OR ID IN (
SELECT ID FROM photos WHERE ID > currentID ORDER BY ID ASC LIMIT 2
) ORDER BY ID ASC
【讨论】:
您不应该在 WHERE 子句中使用 OR 而不是 AND 吗?【参考方案4】:如果您只是对 id 的上一条和下一条记录感兴趣,您不能只使用一个 where 子句来限制 WHERE id=xx, xx-1, xx-1, xx+1, xx+2 使用多个 WHERE子句或使用 WHERE IN ?
【讨论】:
这将适用于您有一个连续的标识列的理想世界,但有时您最终会出现间隙(插入失败、删除等)。我发现最好使用 TOP x 结合 WHERE 来获得最接近的。以上是关于在单个 SQL 查询中获取两个下一个和两个上一个条目的主要内容,如果未能解决你的问题,请参考以下文章
如何使用单个 SQL 聚合函数查询为同一个聚合函数获取多个结果?