[英]Postgres Next/Previous row SQL Query
我在Postgres 9.1數據庫中有以下表結構,但如果可能,理想的解決方案應該是DB不可知的:
Table: users |id|username| |1 |one | |2 |two | |3 |three | Table: items |id|userid|itemname|created | |1 |1 |a |timestamp| |2 |1 |b |timestamp| |3 |1 |c |timestamp| |4 |2 |d |timestamp| |5 |2 |e |timestamp| |6 |2 |f |timestamp| |7 |3 |g |timestamp| |8 |3 |h |timestamp| |9 |3 |i |timestamp|
我有一個查詢(視圖),提供下一個和上一個item.id.
例如
View: UserItems |id|userid|itemname|nextitemid|previtemid|created | |1 |1 |a |2 |null |timestamp| |2 |1 |b |3 |1 |timestamp| |3 |1 |c |4 |2 |timestamp| |4 |2 |d |5 |3 |timestamp| |5 |2 |e |6 |4 |timestamp| |6 |2 |f |7 |5 |timestamp| |7 |3 |g |8 |6 |timestamp| |8 |3 |h |9 |7 |timestamp| |9 |3 |i |null |8 |timestamp|
我可以使用以下查詢執行此操作:
SELECT
DISTINCT i.id AS id,
i.userid AS userid,
i.itemname AS itemname,
LEAD(i.id) OVER (ORDER BY i.created DESC) AS nextitemid,
LAG(i.id) OVER (ORDER BY i.created DESC) AS previtemid,
i.created AS created
FROM items i
LEFT JOIN users u
ON i.userid = u.id
ORDER BY i.created DESC;
你能幫忙解決以下問題嗎:
1)有沒有辦法使ids包裹即
2)是否存在一種通過用戶ID對下一個和前一個itemid進行分組的高效方法,例如
View: UserItems |id|userid|itemname|nextitemid|previtemid|nextuseritemid|prevuseritemid|created | |1 |1 |a |2 |9 |2 |3 |timestamp| |2 |1 |b |3 |1 |3 |1 |timestamp| |3 |1 |c |4 |2 |1 |2 |timestamp| |4 |2 |d |5 |3 |5 |6 |timestamp| |5 |2 |e |6 |4 |6 |4 |timestamp| |6 |2 |f |7 |5 |4 |5 |timestamp| |7 |3 |g |8 |6 |8 |9 |timestamp| |8 |3 |h |9 |7 |9 |7 |timestamp| |9 |3 |i |1 |8 |7 |8 |timestamp|
Q1:FIRST_VALUE / LAST_VALUE
Q2:PARTITION BY(正如Roman Pekar已經建議的那樣)
SELECT
DISTINCT 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 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) AS nextitemid,
COALESCE(LAG(i.id) OVER (ORDER BY i.created DESC)
,LAST_VALUE(i.id) OVER (ORDER BY i.created DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) 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 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) AS nextuseritemid,
COALESCE(LAG(i.id) OVER (PARTITION BY i.userid ORDER BY i.created DESC)
,LAST_VALUE(i.id) OVER (PARTITION BY i.userid ORDER BY i.created DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) AS prevuseritemid,
i.created AS created
FROM items i
LEFT JOIN users u
ON i.userid = u.id
ORDER BY i.created DESC;
更新我忘記了PostgreSQL中的first_value和last_value函數 ,多虧了他提醒我的dnoeth。 但是,他的查詢不起作用,因為last_value
正在使用默認窗口RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW並且不會返回正確的結果,所以你要么必須改變over子句內的范圍要么使用first_value
和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
以前的版本
我想你可以這樣做:
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;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.