【问题标题】:sql pulling a row for next or previous row of a current rowsql为当前行的下一行或上一行拉一行
【发布时间】:2010-11-18 13:40:44
【问题描述】:
编号 |照片标题 |创建日期 XEi43 |我的家人 | 2009年08月04日 dDls |朋友圈 | 2009年08月05日 32kJ |美丽的地方| 2009年08月06日 EOIk |工作到很晚 | 2009年08月07日

假设我有 id 32kJ。如何获得下一行或上一行?

【问题讨论】:

  • “下一个”或“上一个”的概念取决于顺序。您可能会以编程方式执行此操作,方法是使用 ado.net 或其他技术检索 DataSet,然后遍历该数据表示的记录。
  • 如果您的 id 字段是连续的和数字的,这很容易实现,但您使用字母字符的事实使它变得更加棘手。 scottklarr.com/topic/111/…

标签: sql mysql


【解决方案1】:

这是我用来查找上一个/下一个记录的方法。表中的任何列都可以用作排序列,并且不需要连接或讨厌的 hack:

下一条记录(日期大于当前记录):

SELECT id, title, MIN(created) AS created_date
FROM photo
WHERE created >
  (SELECT created FROM photo WHERE id = '32kJ')
GROUP BY created
ORDER BY created ASC
LIMIT 1;

上一个记录(日期小于当前记录):

SELECT id, title, MAX(created) AS created_date
FROM photo
WHERE created <
  (SELECT created FROM photo WHERE id = '32kJ')
GROUP BY created
ORDER BY created DESC
LIMIT 1;

例子:

CREATE TABLE `photo` (
    `id` VARCHAR(5) NOT NULL,
    `title` VARCHAR(255) NOT NULL,
    `created` DATETIME NOT NULL,
    INDEX `created` (`created` ASC),
    PRIMARY KEY (`id`)
)
ENGINE = InnoDB;

INSERT INTO `photo` (`id`, `title`, `created`) VALUES ('XEi43', 'my family',       '2009-08-04');
INSERT INTO `photo` (`id`, `title`, `created`) VALUES ('dDls',  'friends group',   '2009-08-05');
INSERT INTO `photo` (`id`, `title`, `created`) VALUES ('32kJ',  'beautiful place', '2009-08-06');
INSERT INTO `photo` (`id`, `title`, `created`) VALUES ('EOIk',  'working late',    '2009-08-07');

SELECT * FROM photo ORDER BY created;
+-------+-----------------+---------------------+
| id    | title           | created             |
+-------+-----------------+---------------------+
| XEi43 | my family       | 2009-08-04 00:00:00 |
| dDls  | friends group   | 2009-08-05 00:00:00 |
| 32kJ  | beautiful place | 2009-08-06 00:00:00 |
| EOIk  | working late    | 2009-08-07 00:00:00 |
+-------+-----------------+---------------------+


SELECT id, title, MIN(created) AS next_date
FROM photo
WHERE created >
  (SELECT created FROM photo WHERE id = '32kJ')
GROUP BY created
ORDER BY created ASC
LIMIT 1;

+------+--------------+---------------------+
| id   | title        | next_date           |
+------+--------------+---------------------+
| EOIk | working late | 2009-08-07 00:00:00 |
+------+--------------+---------------------+

SELECT id, title, MAX(created) AS prev_date
FROM photo
WHERE created <
  (SELECT created FROM photo WHERE id = '32kJ')
GROUP BY created
ORDER BY created DESC
LIMIT 1;

+------+---------------+---------------------+
| id   | title         | prev_date           |
+------+---------------+---------------------+
| dDls | friends group | 2009-08-05 00:00:00 |
+------+---------------+---------------------+

【讨论】:

  • 我还没有尝试过,但我确信这会拉出结果,我只是想知道,如果查询更快的话,哪一个。
  • 如果您已经对结果进行了排序并限制为 1 行,为什么还要使用聚合函数?
【解决方案2】:

我知道您使用的是 MySQL,但仅供参考,以下是您如何使用 Oracle 的分析函数 LEAD 和 LAG 执行此操作:

select empno, ename, job,
  lag(ename, 1) over (order by ename) as the_guy_above_me,
  lead(ename, 2) over (order by ename) as the_guy_two_rows_below_me
from emp
order by ename

我想 Oracle 花钱而 MySQL 免费是有原因的... :-)

此页面显示您how to emulate analytic functions in MySQL

【讨论】:

  • 你也可以在 Postgres 8.4 中获得这些分析函数:p
【解决方案3】:

您想要按日期的下一个/上一行吗?如果是这样,您可以这样做:

select MyTable.*
from MyTable
join
  (select id
   from MyTable
   where created_date < (select created_date from MyTable where id = '32kJ')
   order by created_date desc, id desc
   limit 1
  ) LimitedTable on LimitedTable.id = MyTable.fund_id;

【讨论】:

  • jeremy stein,你能否告诉我,如果我可以从总行中检查当前行的位置(显示 100 行中的 6 行),这个查询可以做到吗?或者我需要扩展查询吗,如果延长,那么我该怎么做?我只想从总行中知道当前行的位置,这样我就可以让它与下一个和上一个一起工作。所以用户知道他们在哪里,就像在 facebook 上一样。
  • 我也想为当前行添加定位,除了下一个和上一个.. 我该怎么做? stackoverflow.com/questions/2036425/…
  • 是的,您可以执行这些操作,但从调用应用程序执行此操作可能更有意义。
【解决方案4】:

使用 Mike 的 MAX/MIN 技巧,我们可以对各种事情进行上一个\下一个跳跃。此 msAccess 示例将返回股票市场数据表中每条记录的前一个收盘价。注意:“

SELECT 
   tableName.Date,
   tableName.Close,
   (SELECT Close 
      FROM tableName 
      WHERE Date = (SELECT MAX(Date) FROM tableName 
                     WHERE Date <= iJoined.yesterday)
   ) AS previousClose
FROM 
 (SELECT Date, DateAdd("d",-1, Date) AS yesterday FROM tableName)
  AS iJoined 
INNER JOIN 
    tableName ON tableName.Date=iJoined.Date;

...'yesterday' 演示使用函数(Date-1) 跳转;我们可以简单地使用...

(SELECT Date FROM tableName) AS iJoined
  /* previous record */
(SELECT MAX(Date) FROM tableName WHERE Date < iJoined.Date)
  /* next record */
(SELECT MIN(Date) FROM tableName WHERE Date > iJoined.Date)

诀窍是我们可以在 whatever(s) 中使用 MAX\MIN 和跳转函数()

【讨论】:

    【解决方案5】:

    可怕的 hack - 我不喜欢这个,但可能有用..

    with yourresult as
    (
    select id, photo_title, created_date, ROW_NUMBER() over(order by created_date) as 'RowNum' from your_table
    )
    -- Previous
    select * from yourresult where RowNum = ((select RowNum from yourresult where id = '32kJ') -1)
    -- Next
    select * from yourresult where RowNum = ((select RowNum from yourresult where id = '32kJ') +1)
    

    那有什么用?

    【讨论】:

    • 很遗憾,可能不会。这是 MS SQL - 昨天午餐我突然想到了,但没有太多时间 - 我今晚再看看..
    • 我收到此错误 #1064 - 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在“with yourresult as (select photo_id, title, added_date, ROW_NUMBER() over(ord' at line 1) 附近使用正确的语法
    【解决方案6】:

    我将 id 视为表中的主键(以及“行号”),并用它来比较每条记录与之前的记录。 以下代码必须有效。

    CREATE SCHEMA temp
    create table temp.emp (id integer,name varchar(50), salary  varchar(50));
    insert into temp.emp values(1,'a','25000');
    insert into temp.emp values(2,'b','30000');
    insert into temp.emp values(3,'c','35000');
    insert into temp.emp values(4,'d','40000');
    insert into temp.emp values(5,'e','45000');
    insert into temp.emp values(6,'f','20000');
    
    select * from temp.emp
    
    SELECT
        current.id, current.name, current.salary,
        case 
            when current.id = 1 then current.salary 
            else 
                case
                    when current.salary > previous.salary then previous.salary
                    else current.salary  
                end
         end
    FROM
        temp.emp AS current
        LEFT OUTER JOIN temp.emp AS previous
        ON current.id = previous.id + 1
    

    【讨论】:

    • 您是否需要解决方案来比较单个查询中的上一条和下一条记录。所以请在上面尝试..
    猜你喜欢
    • 2012-06-12
    • 1970-01-01
    • 2021-10-27
    • 2016-06-29
    • 2016-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多