【问题标题】:Get Previous and Next record from database and loop them从数据库中获取上一条和下一条记录并循环它们
【发布时间】:2019-05-21 04:14:53
【问题描述】:

我有一个 ID 从 1 到 8 的表。我想要这样的东西

如果我在 4,我应该得到 3,5

如果我在 1,我应该得到 8,2

如果在 8,我应该得到 7, 1

基本上循环遍历表记录

这是我当前的代码

-- previous or last, if there is no previous
SELECT *
FROM news
WHERE id < 1 OR id = MAX(id)
ORDER BY id DESC
LIMIT 1

-- next or first, if there is no next
SELECT *
FROM news
WHERE id > 1 OR id = MIN(id)
ORDER BY id ASC
LIMIT 1

但它说组函数的使用无效。有什么帮助吗?

【问题讨论】:

  • 您是在尝试创建函数、循环还是选择?向我们展示数据库架构、示例数据、当前和预期输出。请阅读How-to-Ask 这里是START 了解如何提高问题质量并获得更好答案的好地方。
  • 我想要获取上一条和下一条记录。很简单。
  • 如果您显示示例数据和预期输出会很简单。
  • 假设我在表中只有 id 字段。这会有帮助吗?
  • 类似的东西。样本数据和预期输出stackoverflow.com/a/46409126/3470178 或此stackoverflow.com/questions/54890579/…

标签: mysql sql


【解决方案1】:

如果 id 是连续的,你可以这样做:

SQL DEMO

SELECT o.id, 
       COALESCE(b.id, (SELECT MAX(ID) FROM Table1)) as before_id,
       COALESCE(a.id, (SELECT MIN(ID) FROM Table1)) as after_id
FROM Table1 o
LEFT JOIN Table1 b
  ON o.id = b.id + 1
LEFT JOIN Table1 a  
  ON o.id = a.id - 1
ORDER BY o.id  

输出

| id | before_id | after_id |
|----|-----------|----------|
|  1 |         8 |        2 |
|  2 |         1 |        3 |
|  3 |         2 |        4 |
|  4 |         3 |        5 |
|  5 |         4 |        6 |
|  6 |         5 |        7 |
|  7 |         6 |        8 |
|  8 |         7 |        1 |

如果 id 不是连续的,您需要使用 row_number() (mysql ver 8+) 或会话变量来创建序列。

【讨论】:

  • OP 想要 3,4 换 4。
  • 抱歉,4 是 3,5
  • 我觉得这个解决方案太复杂了。它还假设 id 没有间隙。
  • @GordonLinoff 在我的辩护中,我已经说过假设没有间隙,如果有间隙就需要一个序列。
  • 如果没有间隙,则不需要连接。
【解决方案2】:

我猜您想在用户查看新闻文章时显示“上一个”和“下一个”按钮。当您获取文章数据时,我会在主查询中获取上一个和下一个 ID:

select n.*, -- select columns you need
  coalesce(
    (select max(n1.id) from news n1 where n1.id < n.id ),
    (select max(id) from news)
  ) as prev_id,
  coalesce(
    (select min(n1.id) from news n1 where n1.id > n.id ),
    (select min(id) from news)
  ) as next_id
from news n
where n.id = ?

db-fiddle demo

现在您可以使用prev_idnext_id 作为按钮,或者通过简单的select * from news where id = ? 查询预取相应的文章。

【讨论】:

    【解决方案3】:

    您可以删除方法中的过滤并将逻辑添加到ORDER BY

    (SELECT n.*
     FROM news
     ORDER BY (id < 1), id DESC
     LIMIT 1
    ) UNION ALL
    (SELECT n.*
     FROM news
     ORDER BY (id > 1), id ASC
     LIMIT 1
    ) ;
    

    如果您希望id 值在一行中,您可以使用聚合:

    select coalesce(max(case when id < 1 then id end), max(id)) as prev_id,
           coalesce(min(case when id > 1 then id end), min(id)) as next_id
    from news n;
    

    在这两种情况下,1 都是样本 id,“1”可以替换为任何值。

    【讨论】:

    • 第二个查询如何查找上一个和下一个?还是只针对 id 为 1 的行?
    • @JuanCarlosOropeza 。 . .如果id 是最小值,则第一个max() 返回NULL,第二个返回。否则,将从第一个 max() 返回“上一个”id。
    • 我现在明白了。所以只返回带有id = 1 的行的prev 和max 就像一个函数?在这种情况下@row_id = 1
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多