Pan*_*red 4 sql postgresql subquery nearest-neighbor correlated-subquery
我正在使用PostgreSQL 9,我想在RP所有元组中查找表中最近的邻居RQ,比较日期(t),但是我得到了这个错误:
错误:FROM中的子查询不能引用相同查询级别的其他关系
使用此查询:
SELECT *
FROM RQ, (SELECT * FROM RP ORDER BY ABS(RP.t - RQ.t) LIMIT 1) AS RA
Run Code Online (Sandbox Code Playgroud)
RQ.t在子查询中似乎是问题所在.我怎样才能避免这个错误?如何从子查询访问RQ?
LATERAL加入允许,并与Postgres 9.3一起介绍.细节:
原因在于错误消息.FROM列表的一个元素不能FROM在同一级别引用列表的另一个元素.对于同一级别的对等体,它是不可见的.您可以使用相关子查询来解决此问题:
SELECT *, (SELECT t FROM rp ORDER BY abs(rp.t - rq.t) LIMIT 1) AS ra
FROM rq
Run Code Online (Sandbox Code Playgroud)
显然,你不关心从哪一行中RP选择一行等距离的行,所以我也这样做.
但是,SELECT列表中的子查询表达式只能返回一列.如果您需要表中的多个或多个列RP,请使用类似此子查询构造的内容:
我假设id两个表中都存在主键.
SELECT id, t, (ra).*
FROM (
SELECT *, (SELECT rp FROM rp ORDER BY abs(rp.t - rq.t) LIMIT 1) AS ra
FROM rq
) x;
Run Code Online (Sandbox Code Playgroud)
相关的子查询因性能不佳而臭名昭着.这种查询 - 虽然显然计算你想要的东西 - 会特别糟糕,因为表达式rp.t - rq.t不能使用索引.较大的桌子会使性能急剧恶化.
这样重写后的查询应该能够利用一个在指数RP.t,其应执行多少与大表更快.
WITH x AS (
SELECT *
,(SELECT t
FROM rp
WHERE rp.t < rq.t
ORDER BY rp.t DESC
LIMIT 1) AS t_pre
,(SELECT t
FROM rp
WHERE rp.t >= rq.t
ORDER BY rp.t
LIMIT 1) AS t_post
FROM rq
)
SELECT id, t
,CASE WHEN (t_post - t) < (t - t_pre)
THEN t_post
ELSE COALESCE(t_pre, t_post) END AS ra
FROM x;
Run Code Online (Sandbox Code Playgroud)
再次,如果你想要整行:
WITH x AS (
SELECT *
,(SELECT rp
FROM rp
WHERE rp.t < rq.t
ORDER BY rp.t DESC
LIMIT 1) AS t_pre
,(SELECT rp
FROM rp
WHERE rp.t >= rq.t
ORDER BY rp.t
LIMIT 1) AS t_post
FROM rq
), y AS (
SELECT id, t
,CASE WHEN ((t_post).t - t) < (t - (t_pre).t)
THEN t_post
ELSE COALESCE(t_pre, t_post) END AS ra
FROM x
)
SELECT id AS rq_id, t AS rq_t, (ra).*
FROM y
ORDER BY 2;
Run Code Online (Sandbox Code Playgroud)
注意括号与复合类型的使用!没有paren在这里是多余的.在这里和这里的手册中有更多相关信息.
使用PostgreSQL 9.1进行测试.在sqlfiddle上演示.
| 归档时间: |
|
| 查看次数: |
8636 次 |
| 最近记录: |