PostgreSQL 分析函数窗口化以查找列中的下一个值
Posted
技术标签:
【中文标题】PostgreSQL 分析函数窗口化以查找列中的下一个值【英文标题】:PostgreSQL analytic function windowing to find the next value in column 【发布时间】:2017-12-13 00:15:21 【问题描述】:我有一个使用 PostgreSQL 创建的数据集,如下所示:
SELECT T.*
FROM
(
WITH REF_TABLE AS
(
SELECT 22 AS "UNIT", 1 AS "CYCLE", 5.3 AS "FIRST_SHIFT", 9.56 AS "LAST_SHIFT", 1 AS "ROUTE" FROM DUAL
UNION
SELECT 22 AS "UNIT", 1 AS "CYCLE", 5.3 AS "FIRST_SHIFT", 9.56 AS "LAST_SHIFT", 2 AS "ROUTE" FROM DUAL
UNION
SELECT 22 AS "UNIT", 1 AS "CYCLE", 5.3 AS "FIRST_SHIFT", 9.56 AS "LAST_SHIFT", 3 AS "ROUTE" FROM DUAL
UNION
SELECT 22 AS "UNIT", 1 AS "CYCLE", 5.3 AS "FIRST_SHIFT", 9.56 AS "LAST_SHIFT", 4 AS "ROUTE" FROM DUAL
UNION
SELECT 22 AS "UNIT", 2 AS "CYCLE", 3.8 AS "FIRST_SHIFT", 6.25 AS "LAST_SHIFT", 1 AS "ROUTE" FROM DUAL
UNION
SELECT 22 AS "UNIT", 2 AS "CYCLE", 3.8 AS "FIRST_SHIFT", 6.25 AS "LAST_SHIFT", 3 AS "ROUTE" FROM DUAL
UNION
SELECT 22 AS "UNIT", 3 AS "CYCLE", 7.0 AS "FIRST_SHIFT", 10.05 AS "LAST_SHIFT", 1 AS "ROUTE" FROM DUAL
UNION
SELECT 22 AS "UNIT", 3 AS "CYCLE", 7.0 AS "FIRST_SHIFT", 10.05 AS "LAST_SHIFT", 2 AS "ROUTE" FROM DUAL
UNION
SELECT 22 AS "UNIT", 3 AS "CYCLE", 7.0 AS "FIRST_SHIFT", 10.05 AS "LAST_SHIFT", 3 AS "ROUTE" FROM DUAL
UNION
SELECT 22 AS "UNIT", 3 AS "CYCLE", 7.0 AS "FIRST_SHIFT", 10.05 AS "LAST_SHIFT", 4 AS "ROUTE" FROM DUAL
UNION
SELECT 22 AS "UNIT", 3 AS "CYCLE", 7.0 AS "FIRST_SHIFT", 10.05 AS "LAST_SHIFT", 5 AS "ROUTE" FROM DUAL
UNION
SELECT 22 AS "UNIT", 4 AS "CYCLE", 4.3 AS "FIRST_SHIFT", 8.10 AS "LAST_SHIFT", 4 AS "ROUTE" FROM DUAL
UNION
SELECT 22 AS "UNIT", 4 AS "CYCLE", 4.3 AS "FIRST_SHIFT", 8.10 AS "LAST_SHIFT", 5 AS "ROUTE" FROM DUAL
UNION
SELECT 22 AS "UNIT", 4 AS "CYCLE", 4.3 AS "FIRST_SHIFT", 8.10 AS "LAST_SHIFT", 8 AS "ROUTE" FROM DUAL
)
SELECT * FROM REF_TABLE
)
T
Dataset
UNIT | CYCLE | FIRST_SHIFT | LAST_SHIFT | ROUTE
------+-------+-------------+------------+-------
22 | 1 | 5.3 | 9.56 | 1
22 | 1 | 5.3 | 9.56 | 2
22 | 1 | 5.3 | 9.56 | 3
22 | 1 | 5.3 | 9.56 | 4
22 | 2 | 3.8 | 6.25 | 1
22 | 2 | 3.8 | 6.25 | 3
22 | 3 | 7.0 | 10.05 | 1
22 | 3 | 7.0 | 10.05 | 2
22 | 3 | 7.0 | 10.05 | 3
22 | 3 | 7.0 | 10.05 | 4
22 | 3 | 7.0 | 10.05 | 5
22 | 4 | 4.3 | 8.10 | 4
22 | 4 | 4.3 | 8.10 | 5
22 | 4 | 4.3 | 8.10 | 8
我无法为此数据集锻炼正确的 PostgreSQL 分析函数(LEAD、LAG 或 FIRST_VALUE、LAST_VALUE)窗口;但 想生成如下输出:
【问题讨论】:
显示输出是好的(如果不是图像会更好),但您还应该用文字描述所需的行为。SELECT ... FROM DUAL
听起来好像你真的在使用 Oracle
【参考方案1】:
我更确定我在这里发明了一个方轮,但万一没有人给你正常的解决方案:
t=# with a as (
select *
, case when r = max(r) over (partition by u,c,f) then row_number() over () else 0 end casex
, case when r = min(r) over (partition by u,c,f) then row_number() over () else 0 end casen
, lead(f) over (partition by u order by u,c)
, lag(l) over (partition by u order by u,c)
from t
)
, b as (
select *
, max("casex") over(partition by u,c) x
, max("casen") over(partition by u,c) n
from a
)
select u,c,f,l,r
, nth_value("lead","x"::int) over()
, nth_value("lag","n"::int) over()
from b;
u | c | f | l | r | nth_value | nth_value
----+---+-----+-------+---+-----------+-----------
22 | 1 | 5.3 | 9.56 | 1 | 3.8 |
22 | 1 | 5.3 | 9.56 | 2 | 3.8 |
22 | 1 | 5.3 | 9.56 | 3 | 3.8 |
22 | 1 | 5.3 | 9.56 | 4 | 3.8 |
22 | 2 | 3.8 | 6.25 | 1 | 7.0 | 9.56
22 | 2 | 3.8 | 6.25 | 3 | 7.0 | 9.56
22 | 3 | 7.0 | 10.05 | 1 | 4.3 | 6.25
22 | 3 | 7.0 | 10.05 | 2 | 4.3 | 6.25
22 | 3 | 7.0 | 10.05 | 3 | 4.3 | 6.25
22 | 3 | 7.0 | 10.05 | 4 | 4.3 | 6.25
22 | 3 | 7.0 | 10.05 | 5 | 4.3 | 6.25
22 | 4 | 4.3 | 8.10 | 4 | | 10.05
22 | 4 | 4.3 | 8.10 | 5 | | 10.05
22 | 4 | 4.3 | 8.10 | 8 | | 10.05
(14 rows)
我再次在这里编写了一个逐步逻辑选择的代码,但我确信有一些数学技巧可以缩短方式
【讨论】:
以上是关于PostgreSQL 分析函数窗口化以查找列中的下一个值的主要内容,如果未能解决你的问题,请参考以下文章