请参阅窗口函数中的当前行

时间:2017-03-22 13:41:20

标签: postgresql window-functions

是否可以引用窗口分区中的当前行?我想做类似以下的事情:

SELECT min(ABS(variable - CURRENT.variable)) over (order by criterion RANGE UNBOUNDED PRECEDING)

也就是说,我想在给定的分区中找到最接近当前值的变量。有可能做那样的事吗?

例如,来自:

criterion | variable 1 2 2 4 3 2 4 7 5 6

我们会获得:

null 2 0 3 1

由于

3 个答案:

答案 0 :(得分:0)

据我所知,窗口函数无法做到这一点。

但可以通过自我加入来完成:

SELECT a.id,
       a.variable,
       min(abs(a.variable - b.variable))
FROM mydata a
   LEFT JOIN mydata b
      ON (b.criterion < a.criterion)
GROUP BY a.id, a.variable
ORDER BY a.id;

答案 1 :(得分:0)

如果我理解正确:

with t (v) as (values (-5),(-2),(0),(1),(3),(10))
select v,
    least(
        v - lag(v) over (order by v),
        lead(v) over (order by v) - v
    ) as closest
from t
;
 v  | closest                                                                                                          
----+---------                                                                                                         
 -5 |       3                                                                                                          
 -2 |       2                                                                                                          
  0 |       1
  1 |       1
  3 |       2
 10 |       7

答案 2 :(得分:0)

希望这可以帮助你(注意性能问题)。 我在MSSQL中试过这个(在底部你会发现POSTGRESQL版本):

CREATE TABLE TX (CRITERION INT, VARIABILE INT);
INSERT INTO TX VALUES (1,2), (2,4),(3,2),(4,7), (5,6);

SELECT CRITERION, MIN_DELTA FROM 
(
SELECT TX.CRITERION 
, MIN(ABS(B.TX2_VAR - TX.VARIABILE)) OVER (PARTITION BY TX.CRITERION) AS MIN_DELTA
, RANK() OVER (PARTITION BY TX.CRITERION ORDER BY ABS(B.TX2_VAR - TX.VARIABILE) ) AS MIN_RANK
FROM TX
CROSS APPLY (SELECT TX2.CRITERION AS TX2_CRIT, TX2.VARIABILE AS TX2_VAR FROM TX TX2 WHERE TX2.CRITERION < TX.CRITERION) B
) C
WHERE MIN_RANK=1
ORDER BY CRITERION 
;

输出:

CRITERION   MIN_DELTA
----------- -----------
2           2
3           0
4           3
5           1

POSTGRESQL版本(在Rextester http://rextester.com/VMGJ87600上测试):

CREATE TABLE TX (CRITERION INT, VARIABILE INT);
INSERT INTO TX VALUES (1,2), (2,4),(3,2),(4,7), (5,6);
SELECT * FROM TX;

SELECT CRITERION, MIN_DELTA FROM 
(
SELECT TX.CRITERION 
, MIN(ABS(B.TX2_VAR - TX.VARIABILE)) OVER (PARTITION BY TX.CRITERION) AS MIN_DELTA
, RANK() OVER (PARTITION BY TX.CRITERION ORDER BY ABS(B.TX2_VAR - TX.VARIABILE) ) AS MIN_RANK
FROM TX
LEFT   JOIN LATERAL (SELECT TX2.CRITERION AS TX2_CRIT, TX2.VARIABILE AS TX2_VAR FROM TX TX2 WHERE TX2.CRITERION < TX.CRITERION) B ON TRUE
) C
WHERE MIN_RANK=1
ORDER BY CRITERION 
;

DROP TABLE TX;

输出:

    criterion   variabile
1   1   2
2   2   4
3   3   2
4   4   7
5   5   6

    criterion   min_delta
1   1   NULL
2   2   2
3   3   0
4   4   3
5   5   1