简体   繁体   English

SQL - 在给定特定WHERE子句的情况下查找下一行和上一行

[英]SQL - find next and previous rows given a particular WHERE clause

I have a MySQL table called bb_posts used by a bbPress forum. 我有一个名为bb_posts的MySQL表,由bbPress论坛使用。 It has an autoincrement field called topid_id and another field called topic_poster. 它有一个名为topid_id的自动增量字段和另一个名为topic_poster的字段。

I'm trying to write a function that finds the "next post by the same author". 我正在尝试编写一个找到“同一作者的下一篇文章”的函数。 So, for instance, say the user is on a particular page that displays topic 123. If you do a SQL query: 因此,例如,假设用户位于显示主题123的特定页面上。如果您执行SQL查询:

SELECT *
FROM `bb_topics`
WHERE `topic_poster` = 5
ORDER BY `topic_id` ASC

This might return the following rows: 这可能会返回以下行:

topic_id    topic_poster
6           5
50          5
123         5
199         5
2039        5

What I'd like to do is write a SQL query that returns these two rows: 我想做的是写一个返回这两行的SQL查询:

topic_id    topic_poster
50          5
199         5

This would be the row PRIOR to the row with topic_id of 123, and the row AFTER that row. 这将是具有topic_id为123的行的PRIOR行,以及该行的AFTER行。

If it's too hard to do this in one query, it's definitely OK to break this up into two queries... 如果在一个查询中执行此操作太难了,那么将其分解为两个查询肯定是可以的...

I'd like to avoid doing the whole SQL query ("SELECT * FROM bb_topics WHERE topic_poster = 5") and looping through the results, because the result set is sometimes huge. 我想避免做整个SQL查询(“SELECT * FROM bb_topics WHERE topic_poster = 5”)并循环遍历结果,因为结果集有时很大。

Is this possible? 这可能吗? :-) :-)

Next one: 下一个:

SELECT * FROM `bb_topics` 
      WHERE `topic_id` = 
      (select min(`topic_id`) FROM `bb_topics` where `topic_id` > 123
         and `topic_poster` = 5)

Previous one: 前一个:

SELECT * FROM `bb_topics` 
      WHERE `topic_id` = 
      (select max(`topic_id`) FROM `bb_topics` where `topic_id` < 123
         and `topic_poster` = 5)

Both: 都:

SELECT * FROM `bb_topics` 
      WHERE `topic_id` = 
      (select min(`topic_id`) FROM `bb_topics` where `topic_id` > 123
                     and `topic_poster` = 5)
      or `topic_id` = 
      (select max(`topic_id`) FROM `bb_topics` where `topic_id` < 123
                        and `topic_poster` = 5)

Look at this older question as well. 看看这个老问题

My guess is that the UNION with LIMIT 1 performs better than the aggregates in my answer here. 我的猜测是,带有LIMIT 1的UNION比我在这里的答案中的聚合更好。

NOTE: Before downvoting, please read the comment and the first revision of question ;-) 注意:在downvoting之前,请阅读评论和问题的第一个修订;-)

By definition the data on a RDBMS table are not ordered . 根据定义,RDBMS表上的数据不是有序的 It means that when you run a query, if you don't specify an ORDER BY clause, the order can be different from one query to another. 这意味着当您运行查询时,如果未指定ORDER BY子句,则顺序可以从一个查询到另一个查询不同。 Furthermore, you have to consider that the next query is going to (or, at least, may) return a different order . 此外,您必须考虑下一个查询将(或至少可能)返回不同的顺序

Suppose that may be another user on database inserts a new record and the RDBMS considers to put it between the rows you are considering. 假设可能是数据库上的另一个用户插入新记录,并且RDBMS认为将它放在您正在考虑的行之间。 Or the DBA is moving the table to another in online basis (this is possible in Oracle, for instance), in this case the data can be changed on any matter. 或者DBA在线基础上将表移动到另一个表(例如,这在Oracle中是可能的),在这种情况下,可以在任何情况下更改数据。

For your question, you have to build a kind of query result cache to determine prior and next rows on the queries. 对于您的问题,您必须构建一种查询结果缓存,以确定查询的上一行和下一行。

Here's a subtle but efficient way to accomplish this, and it works on even old versions of MySQL which don't support subqueries -- 这是实现这一目标的一种微妙但有效的方法,它甚至适用于不支持子查询的旧版MySQL -

 SELECT * FROM bb_topics AS bb1 LEFT JOIN bb_topics AS bb2 ON bb1.topic_poster = bb2.topic_poster AND bb2.topic_id > bb1.topic_id LEFT JOIN bb_topics AS bb3 ON bb1.topic_poster = bb3.topic_poster AND bb3.topic_id > bb1.topic_id AND bb3.topic_id < bb2.topic_id WHERE bb1.topic_poster = 5 AND bb3.topic_id IS NULL 

This gets you the next adjacent post. 这将使您获得下一个相邻的帖子。 I can fill in the symmetric clauses for the next previous post if it's not self-evident. 如果不明确的话,我可以填写下一篇文章的对称条款。

EDIT - minor corrected alii. 编辑 - 小修正alii。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM