简体   繁体   English

PostgreSQL分析函数开窗以查找列中的下一个值

[英]PostgreSQL analytic function windowing to find the next value in column

I have a data-set created using PostgreSQL as following: 我有一个使用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

I couldn't workout the right PostgreSQL analytic function (LEAD,LAG or FIRST_VALUE, LAST_VALUE) windowing for this data-set; 我无法为此数据集使用正确的PostgreSQL分析功能(LEAD,LAG或FIRST_VALUE,LAST_VALUE)窗口; but would like generate an output as following: 但想要生成如下输出:

在此处输入图片说明

I'm more then sure I'm inventing a square wheel here, but in case no one give you the normal solution: 那么,我可以肯定的是,我在这里发明了方形齿轮,但是如果没有人给您正常的解决方案:

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)

again I coded a step by step logical select here, but I'm sure there are mathematical tricks to shortcut the way 我再次在这里编写了逐步选择逻辑的代码,但是我敢肯定,有一些数学技巧可以捷径

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM