【问题标题】:Query fails with ORA-00904 on Oracle 11 but not on Oracle 19查询在 Oracle 11 上失败并出现 ORA-00904,但在 Oracle 19 上没有
【发布时间】:2022-11-17 08:39:48
【问题描述】:

p 成为主条目表,对于每个主条目,我们要聚合详细条目的集合。明细项目有两种,来自两个不同的来源。此查询在 Oracle 11 上以 ORA-00904: "P"."NAME" invalid identifier 失败,但在 Oracle 19 上运行正常。为什么?

with people (name) as (
  select 'Alice' from dual union all
  select 'Bob' from dual
), apples (name, title) as (
  select 'Alice', 'apple1' from dual union all
  select 'Bob', 'apple2' from dual union all
  select 'Bob', 'apple3' from dual
), pears (name, title) as (
  select 'Alice', 'pear4' from dual union all
  select 'Alice', 'pear5' from dual union all
  select 'Alice', 'pear6' from dual union all
  select 'Bob', 'pear7' from dual union all
  select 'Bob', 'pear8' from dual
)
select p.name
     , (
         select listagg(u.title) within group (order by null)
         from (
           select x.title from apples x where x.name = p.name
           union
           select x.title from pears  x where x.name = p.name
         ) u
       ) as unioned
from people p;

NAME UNIONED
Alice apple1pear4pear5pear6
Bob apple2apple3pear7pear8

fiddle

【问题讨论】:

    标签: oracle oracle11g oracle19c correlated-subquery


    【解决方案1】:

    根据AskTom,在相关子查询中可见外部表别名的深度似乎存在深度限制。 Oracle12c 中删除了此限制。对于Oracle11g,仍然可以重写查询条件,将p.name列提取到更高级别

    select p.name
         , (
             select listagg(u.title) within group (order by null)
             from (
               select x.title, x.name from apples x
               union
               select x.title, x.name from pears  x
             ) u
             where u.name = p.name
           ) unioned
    from people p;
    

    或将 union 拆分为两部分,然后再将它们合并:

    (with ...)
    , parts as (
      select p.name
           , (
               select listagg(x.title) within group (order by null)
               from apples x 
               where x.name = p.name
             ) x
           , (
               select listagg(x.title) within group (order by null)
               from pears x 
               where x.name = p.name
             ) y
      from people p
    )
    select name, x || y from parts;
    

    这实际上是我的第一个想法,但现在看来第一个解决方案足以满足所有情况(至少我想不出任何反例)。在实际情况下,聚合函数是collect而不是listagg,因此合并是使用multiset union而不是||完成的。


    另相关:this question

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多