【发布时间】:2025-12-28 01:35:07
【问题描述】:
我想用过滤子句执行窗口函数,例如:
LAG("date", 1) FILTER (WHERE type='A') OVER (PARTITION BY id ORDER BY id ASC) AS "A_lag_1"
但是,Postgres 不支持此操作,但我无法确定其他方法。详情如下
挑战
输入tab_A:
+----+------+------+
| id | type | date |
+----+------+------+
| 1 | A | 30 |
| 1 | A | 25 |
| 1 | A | 20 |
| 1 | B | 29 |
| 1 | B | 28 |
| 1 | B | 21 |
| 1 | C | 24 |
| 1 | C | 22 |
+----+------+------+
期望的输出:
+----+------+------+---------+---------+---------+---------+---------+---------+
| id | type | date | A_lag_1 | A_lag_2 | B_lag_1 | B_lag_2 | C_lag_1 | C_lag_2 |
+----+------+------+---------+---------+---------+---------+---------+---------+
| 1 | A | 30 | 25 | 20 | 29 | 28 | 24 | 22 |
| 1 | A | 25 | 20 | | | | 24 | 22 |
| 1 | A | 20 | | | | | | |
| 1 | B | 29 | 25 | 20 | 28 | 21 | 24 | 22 |
| 1 | B | 28 | 25 | 20 | 21 | | 24 | 22 |
| 1 | B | 21 | 20 | | | | 24 | 22 |
| 1 | C | 24 | 20 | | 21 | | 22 | |
| 1 | C | 22 | 20 | | 21 | | | |
+----+------+------+---------+---------+---------+---------+---------+---------+
言辞:
- 对于每一行,选择它之前出现的所有行(参见
date列) - 然后对于每个
type('A'、'B'、'C'),将最新的date放入A_lag_1,第二个将最近的(按日期)值放入A_lag_2for @ 987654334@'A',B_lag_1,B_lag_2'B'等。
上面的例子非常简化,在我的实际用例中会有更多的id 值,更多的滞后列迭代A_lag_X 和类型。
可能的解决方案
这个挑战似乎非常适合 window function,因为我想保持相同数量的行 tab_A 并附加与该行相关但过去的信息。
所以使用窗口函数构造它(sqlfiddle):
SELECT
id, type, "date",
LAG("date", 1) FILTER (WHERE type='A') OVER (PARTITION BY id ORDER BY id ASC, "date" DESC) AS "A_lag_1",
LAG("date", 2) FILTER (WHERE type='A') OVER (PARTITION BY id ORDER BY id ASC, "date" DESC) AS "A_lag_2",
LAG("date", 1) FILTER (WHERE type='B') OVER (PARTITION BY id ORDER BY id ASC, "date" DESC) AS "B_lag_1",
LAG("date", 2) FILTER (WHERE type='B') OVER (PARTITION BY id ORDER BY id ASC, "date" DESC) AS "B_lag_2",
LAG("date", 1) FILTER (WHERE type='C') OVER (PARTITION BY id ORDER BY id ASC, "date" DESC) AS "C_lag_1",
LAG("date", 2) FILTER (WHERE type='C') OVER (PARTITION BY id ORDER BY id ASC, "date" DESC) AS "C_lag_2"
FROM tab_A
但是,我收到以下错误:
错误:非聚合窗口函数未实现 FILTER 位置:30
虽然documentation 中引用了此错误,但我无法确定另一种方法。
任何帮助将不胜感激。
其他 SO 问题:
-
1. 这个答案依赖于使用聚合函数,例如
max。但是,这在尝试检索倒数第二行、倒数第三行等时不起作用。
【问题讨论】:
标签: sql postgresql window-functions postgresql-9.6