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
;
问题
我正在处理一个在数据库中使用内核的项目,但我的 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
;