首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >错误: FROM中的子查询不能引用相同查询级别的其他关系。

错误: FROM中的子查询不能引用相同查询级别的其他关系。
EN

Stack Overflow用户
提问于 2012-05-27 11:19:28
回答 2查看 10.9K关注 0票数 5

我正在使用PostgreSQL 9,我希望在表RP中为RQ中的所有元组查找最近的邻居,比较日期(t),但是我得到了以下错误:

错误: FROM中的子查询不能引用相同查询级别的其他关系。

使用此查询:

代码语言:javascript
运行
复制
SELECT *
FROM RQ, (SELECT * FROM RP ORDER BY ABS(RP.t - RQ.t) LIMIT 1) AS RA

子查询中的RQ.t似乎是问题所在。如何避免此错误?如何从子查询访问RQ

EN

回答 2

Stack Overflow用户

发布于 2012-05-27 14:11:04

更新:

LATERAL联接允许这样做,并且是在Postgres9.3中引入的。详细信息:

原因在于错误消息。FROM列表的一个元素不能引用同一级别上的FROM列表的另一个元素。对于同级的同侪来说,它是不可见的。您可以使用相关子查询来解决这一问题。

代码语言:javascript
运行
复制
SELECT *, (SELECT t FROM rp ORDER BY abs(rp.t - rq.t) LIMIT 1) AS ra
FROM   rq

显然,您并不关心从一组同样接近的行中选择RP中的哪一行,所以我也这样做。

但是,SELECT列表中的子查询表达式只能返回一列。如果需要表RP中的多个列或所有列,请使用类似以下子查询构造的内容:

我假设两个表中都存在主键id

代码语言:javascript
运行
复制
SELECT id, t, (ra).*
FROM (
    SELECT *, (SELECT rp FROM rp ORDER BY abs(rp.t - rq.t) LIMIT 1) AS ra
    FROM   rq
    ) x;

关联子查询因性能差的而臭名昭著。这种查询--显然是计算您想要的--特别糟糕,因为表达式rp.t - rq.t不能使用索引。如果使用更大的表,性能将急剧下降。

这个重写的查询应该能够利用RP.t,上的索引,使用大表可以更快地执行

代码语言:javascript
运行
复制
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;

同样,如果您想要整行:

代码语言:javascript
运行
复制
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;

注意括号与复合类型的使用!没有帕伦是多余的。在手册这里这里中有更多关于这一点的信息。

用PostgreSQL 9.1进行测试。在广场小提琴上的演示。

票数 6
EN

Stack Overflow用户

发布于 2012-05-28 01:22:21

相关的子查询,没有索引,无论如何都要进行交叉连接。因此,表达查询的另一种方式是:

代码语言:javascript
运行
复制
select rp.*, min(abs(rp.t - rq.t))
from rp cross join
     rq
group by <rp.*> -- <== need to replace with all columns

还有另一种方法,它更复杂一些。这需要使用累积和。

我的想法是。将所有rp和rq值合并在一起。现在,用最近的rp值来枚举它们。也就是说,为rp创建一个标志,并接受累积和。因此,两个rp值之间的所有rq值都具有相同的rp指标。

与给定rq值最接近的值具有与rq值相同或更多的rp索引。计算rq_index使用累积和。

下面的查询将两者结合在一起:

代码语言:javascript
运行
复制
with rqi as (select t.*, sum(isRQ) over (order by t) as rq_index
             from (select rq.t, 0 as isRP, <NULL for each rp column>
                   from rq
                   union all
                   select rq.t, 1 as isRP, rp.* 
                   from rp
                  ) t
            ) t
select rp.*,
       (case when abs(rqprev.t - rp.t) < abs(rqnext.t - rp.t)
             then abs(rqprev.t - rp.t)
             else abs(rqnext.t - rp.t)
        end) as closest_value
from (select *
      from t
      where isRP = 0
     ) rp join
     (select *
      from t
      where isRP = 1
     ) rqprev
     on rp.rp_index = rqprev.rp_index join
     (select *
      from t
      where isRP = 1
     ) rqnext
     on rp.rp_index+1 = rpnext.rq_index

这种方法的优点是没有交叉连接,也没有相关的子查询。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10773568

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档