Postgres Next/Previous row SQL Query

前端 未结 2 933
刺人心
刺人心 2021-01-04 06:41

I have the following table structures in a Postgres 9.1 database but the ideal solution should be DB agnostic if possible:

Table: users
|id|username|
|1 |one              


        
2条回答
  •  Happy的楠姐
    2021-01-04 07:31

    update I've forgot about first_value and last_value functions in PostgreSQL, thanks to dnoeth he reminded me about it. However, his query is not working, because last_value is working with default window RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW and will not return correct results, so you either have to change range inside the over clause or use first_value with order by asc:

    select
        i.id as id,
        i.userid as userid,
        i.itemname as itemname,
        coalesce(
            lead(i.id) over(order by i.created desc),
            first_value(i.id) over(order by i.created desc)
        ) as nextitemid,
        coalesce(
            lag(i.id) over(order by i.created desc),
            first_value(i.id) over(order by i.created asc)
        ) as previtemid,
        coalesce(
            lead(i.id) over(partition by i.userid order by i.created desc),
            first_value(i.id) over(partition by i.userid order by i.created desc)
        ) as nextuseritemid,
        coalesce(
            lag(i.id) over(partition by i.userid order by i.created desc),
            first_value(i.id) over(partition by i.userid order by i.created asc)
        ) as prevuseritemid,
        i.created as created
    from items as i
       left outer join users as u on u.id = i.userid
    order by i.created desc
    

    sql fiddle demo

    previous version
    I think you could do this:

    SELECT
      i.id AS id,
      i.userid AS userid,
      i.itemname AS itemname,
      coalesce(
          LEAD(i.id) OVER (ORDER BY i.created DESC),
          (select t.id from items as t order by t.created desc limit 1)
      ) AS nextitemid,
      coalesce(
          LAG(i.id) OVER (ORDER BY i.created DESC),
          (select t.id from items as t order by t.created asc limit 1)
      ) AS previtemid,
      coalesce(
          LEAD(i.id) OVER (partition by i.userid ORDER BY i.created DESC),
          (select t.id from items as t where t.userid = i.userid order by t.created desc limit 1)
      ) AS nextuseritemid,
      coalesce(
          LAG(i.id) OVER (partition by i.userid ORDER BY i.created DESC),
          (select t.id from items as t where t.userid = i.userid order by t.created asc limit 1)
      ) AS prevuseritemid,
      i.created AS created
    FROM items i
      LEFT JOIN users u
      ON i.userid = u.id
    ORDER BY i.created DESC;
    

    sql fiddle demo

提交回复
热议问题