dav*_*vec 13 sql postgresql ansi-sql
我在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;
Run Code Online (Sandbox Code Playgroud)
你能帮忙解决以下问题吗:
1)有没有办法使ids包裹即
2)是否存在一种通过用户ID对下一个和前一个itemid进行分组的高效方法,例如
注意:在此示例中,用户的itemid是顺序的,实际数据不是这种情况,每个用户的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|
dno*_*eth 12
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;
Run Code Online (Sandbox Code Playgroud)
更新我忘记了PostgreSQL中的first_value和last_value函数,多亏了他提醒我的dnoeth.然而,他的查询不工作,因为last_value
正在与默认的窗口之间的范围内UNBOUNDED PRECEDING AND CURRENT ROW并且不会返回正确的结果,所以你要么必须更改范围过子句中,或使用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
Run Code Online (Sandbox Code Playgroud)
以前的版本
我认为你可以这样做:
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;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
23779 次 |
最近记录: |