PostgreSQL:加入 Window 函数/部分 Table

PostgreSQL: Joining with Window Function / Partial Table

问题

我正在处理一个在数据库中使用内核的项目,但我的 PostgreSQL 技能遇到了瓶颈。我加入两个 tables 来计算叉积,即

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

这给出了所有向量之间的叉积。在我的 table

中有以下数据
 a | b | c 
---+---+---
 1 | 1 | 1
 2 | 2 | 2
 3 | 3 | 3

以上命令产生

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

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

尝试次数

我曾尝试使用 window 函数,但未能成功,因为它们仅计算聚合函数。我想加入一行与其相邻的行(即它的 window),但不计算这些行的任何聚合。这些方面的内容:

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,但没有成功。

有什么想法吗?

您可以通过lag()/lead()获取preceding/following行的值。
如果行的顺序由 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
;