更新:
LATERAL 连接允许这样做,并且是在 Postgres 9.3 中引入的。详情:
原因在错误消息中。 FROM 列表的一个元素不能引用同一级别的FROM 列表的另一个元素。对于同一级别的对等方来说,它是不可见的。
您可以使用相关子查询来解决这个问题:
SELECT *, (SELECT t FROM rp ORDER BY abs(rp.t - rq.t) LIMIT 1) AS ra
FROM rq
显然,您并不关心您从一组同样接近的行中选择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;
相关子查询因性能不佳而臭名昭著。这种查询——虽然显然是在计算你想要的——尤其会suck,因为表达式rp.t - rq.t 不能使用索引。表越大,性能会急剧下降。
这个重写的查询应该能够利用 RP.t 上的索引,这应该在大表中更快。。 p>
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;
同样,如果你想要整行:
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;
注意复合类型的括号的使用!这里没有多余的括号。有关更多信息,请参阅手册 here 和 here。
使用 PostgreSQL 9.1 测试。 Demo on sqlfiddle.