在我的网络应用程序中,我制作了一个内部邮件系统。我想在每个页面上放置一个“上一个”和一个“下一个”链接(用户查看该消息的位置)。
为了获得下一个和上一个id,我执行两个查询:
对于前一个:
SELECT id FROM pages WHERE (id<$requestedPageId) ORDER BY id DESC LIMIT 1
下一个:
SELECT id FROM pages WHERE (id>$requestedPageId) ORDER BY id LIMIT 1
EXPLAIN表示查询类型为“range”,而rows列表示它将检查id大于或小于页面id(大数字)的所有行。额外的行说“在哪里使用”。
似乎MySQL忽略了我只想要一行。 MySQL不够智能,无法优化这种查询,因此它会找到页面的行并来回搜索第一个匹配的行吗?
是否有更好的方法来获取下一页和上一页的ID?
附加说明:
EDIT1:
所以我目前正在使用的查询:
SELECT id
FROM reports
WHERE (id<$requestedPageId) AND ((isPublic=1) OR (recipientId=$recipient))
ORDER BY id DESC
LIMIT 1
或者当我重新考虑它时,答案说:
SELECT MAX(id)
FROM reports
WHERE (id<$requestedPageId) AND ((isPublic=1) OR (recipientId=$recipient))
答案 0 :(得分:3)
对于之前的
SELECT MAX(id) FROM pages WHERE id<$requestPageId
接下来的
SELECT MIN(id) FROM pages WHERE id>$requestedPageId
答案 1 :(得分:1)
数据库的行为符合预期。由于小于号码(id&lt; $ requestedPageId),您的查询是范围查询。 OR语句使得使用单个索引来查找结果变得更加困难。并且,对结果进行排序意味着它必须获取所有匹配的行才能执行排序,即使您只需要1行。
您无法将其设为“const”类型查询,但您可以使用索引,子查询和/或联合语句对其进行优化。
这是一个统治它们的查询。我不是说这是最好的解决方案,而只是解决问题的一种方法。首先,如果您创建两个索引,此查询将更好地工作,一个在recipientId上,另一个在isPublic上。
SELECT
GREATEST(
( SELECT MAX( id ) FROM reports
WHERE id < $requestedPageId AND recipientId = $recipient ),
( SELECT MAX( id ) FROM reports
WHERE id < $requestedPageId AND isPublic = 1 )
) AS prev_id
LEAST(
( SELECT MIN( id ) FROM reports
WHERE id > $requestedPageId AND recipientId = $recipient ),
( SELECT MIN( id ) FROM reports
WHERE id > $requestedPageId AND isPublic = 1 )
) AS next_id