PostgreSQL:加入窗口函数/部分表

时间:2016-05-07 13:40:25

标签: postgresql join window-functions cross-product

问题

我正在使用数据库中的内核工作,而我的PostgreSQL技能已经碰壁了。我在两个表之间加入来计算交叉乘积,即

SELECT (d1.a * d2.a + d1.b * d2.b) AS dot FROM data d1, data d2

这给了我所有载体之间的交叉产物。在我的表格中包含以下数据

 a | b | c 
---+---+---
 1 | 1 | 1
 2 | 2 | 2
 3 | 3 | 3

以上命令产生

 dot 
-----
   2
   4
   6
 ...

如果我想计算第2行与前一行及其后一行之间的点积,我该如何有效地做到这一点?

尝试

我曾尝试使用窗口函数,但由于它们只计算聚合函数,因此未能这样做。我想连接其相邻行(即其窗口)的行,但不计算任何聚合。这些方面的东西:

SELECT a * a + b * b + c * c
    OVER(rows between 1 preceding and 1 following) as value FROM data data;

我也尝试使用row_number() OVER()。但是对于嵌套的子查询,这看起来很笨拙和低效。

SELECT d1.a * d3.a + d1.b * d3.b + d1.c * d3.c 
    FROM data d1, 
    (SELECT * FROM 
        (SELECT *, row_number() OVER() as index from data) d2 
    WHERE d2.index >= 1 AND d2.index <=3) d3;

最后,我试图在没有运气的情况下深入了解LATERAL

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

您可以按lag() / lead()获取前/后行的​​值 如果行的顺序由a确定,则查询将如下:

SELECT
  a,
  (lag(a, 1, 0) OVER (ORDER BY a)) * (lead(a, 1, 0) OVER (ORDER BY a))
  + (lag(b, 1, 0) OVER (ORDER BY a)) * (lead(b, 1, 0) OVER (ORDER BY a))
  + (lag(c, 1, 0) OVER (ORDER BY a)) * (lead(c, 1, 0) OVER (ORDER BY a)) AS dot_preceding_and_following
FROM ( VALUES
  (1, 1, 1),
  (2, 2, 2),
  (3, 3, 3)
) T(a, b, c)
ORDER BY
  a
;