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

后端 未结 6 1554
抹茶落季
抹茶落季 2020-12-03 05:51
id    |  photo title     |  created_date

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


        
相关标签:
6条回答
  • 2020-12-03 06:21

    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?

    0 讨论(0)
  • 2020-12-03 06:24

    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:

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

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

    0 讨论(0)
  • 2020-12-03 06:25

    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;
    
    0 讨论(0)
  • 2020-12-03 06:27

    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 |
    +------+---------------+---------------------+
    
    0 讨论(0)
  • 2020-12-03 06:32

    Using Mike's MAX/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.

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

    (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()

    0 讨论(0)
  • 2020-12-03 06:34

    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.

    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
    
    0 讨论(0)
提交回复
热议问题