简体   繁体   English

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

[英]sql pulling a row for next or previous row of a current row

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 . 说我有身份证32kJ How would I get the next row or the previous one? 我如何获得下一行或前一行?

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

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中模拟分析函数

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;

Using Mike's MAX/MIN trick we can make previous\\next jumps for all sorts of things. 使用Mike的 MAX / MIN技巧,我们可以为各种事情做出前一个\\下一次跳跃。 This msAccess example will return the previous close for every record in a stock market data table. 此msAccess示例将返回股票市场数据表中每条记录的上一个收盘价。 Note: the '<=' is for weekends and holidays. 注意:'<='适用于周末和假日。

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; ...'昨天'演示使用函数( Date-1 )跳转; we could have simply used... 我们可以简单地使用......

(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和跳转功能的前面\\下一#()

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? 有用吗?

I considered id as primary key in the table (and as "row number"), and used it to compare each record with the record before. 我认为id是表中的主键(和“行号”),并用它来比较每条记录和之前的记录。 The following code must work. 以下代码必须正常工作。

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

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

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