[英]PostgreSQL previous and next group value
The problem is the following:问题如下:
Suppose, I have a table of such view (it is a sub-sample of the table I'm working with):假设,我有一个这样的视图表(它是我正在使用的表的子样本):
| col1 | col2 |
|------|------|
| 1 | a2 |
| 1 | b2 |
| 2 | c2 |
| 2 | d2 |
| 2 | e2 |
| 1 | f2 |
| 1 | g2 |
| 3 | h2 |
| 1 | j2 |
I need to add two new columns我需要添加两个新列
prev
containing the previous value in col1
not equal to the current prev
包含col1
中的先前值不等于当前值next
containing the next value in col1
not equal to the current next
包含col1
不等于当前值的下一个值If there is no previous value, prev
should contain the current col1
's value as well as next
should contain the current value if no next values exist.如果没有以前的值,则prev
应包含当前col1
的值,如果不存在下一个值,则next
应包含当前值。
Result should have the following form:结果应具有以下形式:
| col1 | col2 | prev | next |
|------|------|------|------|
| 1 | a2 | 1 | 2 |
| 1 | b2 | 1 | 2 |
| 2 | c2 | 1 | 1 |
| 2 | d2 | 1 | 1 |
| 2 | e2 | 1 | 1 |
| 1 | f2 | 2 | 3 |
| 1 | g2 | 2 | 3 |
| 3 | h2 | 1 | 1 |
| 1 | j2 | 3 | 1 |
I will be grateful any help.我将不胜感激任何帮助。
If I assume that you have an id
column that specifies the ordering, then this is possible.如果我假设您有一个指定排序的id
列,那么这是可能的。 I'm just not sure this is easily expressed using window functions.我只是不确定这是否可以使用窗口函数轻松表达。
You can use correlated subqueries:您可以使用相关子查询:
select t.*,
(select t2.col1
from t t2
where t2.id < t.id and t2.col1 <> t.col1
order by t2.id desc
fetch first 1 row only
) as prev_col1,
(select t2.col1
from t t2
where t2.id > t.id and t2.col1 <> t.col1
order by t2.id asc
fetch first 1 row only
) as prev_col2
from t;
You can add the coalece()
for missing previous and next values.您可以为缺少上一个和下一个值添加coalece()
。 That is not the interesting part of the problem.这不是问题的有趣部分。
You can try this using combination of window functions lead
, lag
, first_value
, last_value
and sum
.您可以使用窗口函数lead
、 lag
、 first_value
、 last_value
和sum
组合来尝试此操作。
select
t.col1, t.col2, n,
coalesce(first_value(y) over (partition by x order by col2), col1) prev_val,
coalesce(last_value(y2) over (partition by x order by col2
rows between current row and unbounded following), col1) next_val
from (
select
t.*,
case when col1 <> lag(col1) over (order by col2) then lag(col1) over (order by col2) end y,
case when col1 <> lead(col1) over (order by col2) then lead(col1) over (order by col2) end y2,
sum(n) over (order by col2) x
from (
select
t.*,
case when col1 <> lag(col1) over (order by col2) then 1 else 0 end n
from t
) t
) t;
It finds the lead/lag per group of rows.它找到每组行的领先/滞后。
WITH cte AS (
SELECT row_number() over() rowid, *
FROM unnest(array[1,1,2,2,2,1,1,3,1], array['a2','b2','c2','d2','e2','f2','g2','h2','j2']) t(col1,col2)
)
SELECT t.col1,
t.col2,
COALESCE(prev.col1,t.col1) prev,
COALESCE("next".col1,t.col1) "next"
FROM cte t
LEFT JOIN LATERAL (SELECT prev.col1
FROM cte prev
WHERE prev.rowid < t.rowid
AND prev.col1 != t.col1
ORDER BY prev.rowid DESC
LIMIT 1
) prev ON True
LEFT JOIN LATERAL (SELECT "next".col1
FROM cte "next"
WHERE "next".rowid > t.rowid
AND "next".col1 != t.col1
ORDER BY "next".rowid ASC
LIMIT 1
) "next" ON True
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.