MySQL sql为当前行的下一行或上一行拉一行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1259458/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 13:50:44  来源:igfitidea点击:

sql pulling a row for next or previous row of a current row

sqlmysql

提问by Basit

id    |  photo title     |  created_date

XEi43 |  my family       |  2009 08 04
dDls  |  friends group   |  2009 08 05
32kJ  |  beautiful place |  2009 08 06
EOIk  |  working late    |  2009 08 07 

Say I have the id 32kJ. How would I get the next row or the previous one?

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

回答by Mike

This is what I use for finding previous/next records. Any column in your table can be used as the sort column, and no joins or nasty hacks are required:

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

Next record (date greater than current record):

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

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;

Previous record (date less than current record):

以前的记录(日期小于当前记录):

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;

Example:

例子:

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 |
+------+---------------+---------------------+

回答by ObiWanKenobi

I realize that you are using MySQL, but just for reference, here is how you would do this using Oracle's analytic functions LEAD and LAG:

我知道您正在使用 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

I guess there's a reason why Oracle costs money and MySQL is free... :-)

我想甲骨文要花钱,而 MySQL 是免费的,这是有原因的... :-)

This page shows you how to emulate analytic functions in MySQL.

此页面向您展示如何在 MySQL 中模拟分析函数

回答by Jeremy Stein

Did you want the next/previous row by date? If so, you could do this:

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

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;

回答by probably clueless

Using Mike'sMAX/MIN trick we can make previous\next jumps for all sorts of things. This msAccess example will return the previous close for every record in a stock market data table. Note: the '<=' is for weekends and holidays.

使用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' demonstrates using a function(Date-1) jump; we could have simply used...

...'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)

The trick is we can previous\next # of whatever(s)with MAX\MIN and a jump function()

诀窍是,我们可以在以前的\下一#什么(S)与MAX \ MIN和跳转功能()

回答by Rahul More

I considered id as primary key in the table (and as "row number"), and used it to compare each record with the record before. The following code must work.

我将 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

回答by Tikeb

Horrible hack - I don't like this but might work..

可怕的黑客 - 我不喜欢这个,但可能会工作..

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)

That of any use?

那有什么用?