即使列有前缀,也会出现“列模棱两可的定义错误”?

时间:2019-08-02 16:16:02

标签: oracle oracle12c

我有以下sql,它运行正常(Oracle数据库12c企业版版本12.1.0.2.0-64位生产)。

with n as (
    select ntile(cnt) over ( partition by cnt order by Id ) NT, Id
    from t
)
select  n.NT, high.Id
from    (select distinct NT from n) n 
        outer apply (
           select * 
           from n x where x.NT = n.NT and rownum = 1 order by Id
        ) low
        outer apply (
           select * 
           from (select * from n x where x.NT = n.NT order by Id desc) d where rownum = 1
        ) high

现在我将其更改为以下内容,

with n as (
    select ntile(cnt) over ( partition by cnt order by Id ) NT, Id
    from t
)
select  n.NT, phigh.Id -- Error - phigh.Id
from    (select distinct NT from n) n 
        outer apply (
            select * 
            from n x where x.NT = n.NT and rownum = 1 order by Id
        ) low
        outer apply (
            select * 
            from (select * from n x where x.NT = n.NT order by Id desc) d where rownum = 1
        ) high
        outer apply (
            select * 
            from (select * from n x where x.NT = n.NT-1 order by Id desc) d where rownum = 1
        ) phigh

现在它在phigh.Id上出现以下错误:

  

ORA-00918:列定义不明确

     
      
  1. 00000-“列定义不明确”
  2.   

如果我将phigh.Id更改为phigh.*,则第二个查询有效吗?将phigh.Id更改为high.Id也可以。

更新:

试图使用与CTE不同的别名。仍然出现相同的错误

with n as (
    select ntile(cnt) over ( partition by cnt order by Id ) NT, Id
    from t
)
select  n.NT, phigh.Id -- Error - phigh.Id
from    (select distinct NT from n) nt 
        outer apply (
            select * 
            from n x where x.NT = nt.NT and rownum = 1 order by Id
        ) low
        outer apply (
            select * 
            from (select * from n x where x.NT = nt.NT order by Id desc) d where rownum = 1
        ) high
        outer apply (
            select * 
            from (select * from n x where x.NT = nt.NT-1 order by Id desc) d where rownum = 1
        ) phigh

Update2:

以下可测试的查询出错。

with t as (
  select 10 as cnt, 1 as Id from dual
), 
x as (
    select ntile(cnt) over ( partition by cnt order by Id ) NT, Id
    from t
)
select  n.NT, 
        high.Id a, 
        phigh.Id
from    (select distinct NT from x) n 
        outer apply (select * from x where x.NT = n.NT and rownum = 1 order by Id) low
        outer apply (select * from (select * from x where x.NT = n.NT order by Id desc) d where rownum = 1) high
        outer apply (select * from (select * from x where x.NT = n.NT - 1 order by Id desc) d where rownum = 1) phigh

以下代码有效。

with t as (
  select 10 as cnt, 1 as Id from dual
), 
x as (
    select ntile(cnt) over ( partition by cnt order by Id ) NT, Id
    from t
)
select  n.NT, 
        --high.Id a, 
        phigh.Id
from    (select distinct NT from x) n 
        outer apply (select * from x where x.NT = n.NT and rownum = 1 order by Id) low
        --outer apply (select * from (select * from x where x.NT = n.NT order by Id desc) d where rownum = 1) high
        outer apply (select * from (select * from x where x.NT = n.NT - 1 order by Id desc) d where rownum = 1) phigh

2 个答案:

答案 0 :(得分:0)

对于主查询和cte,您应该使用不同的别名,现在它们是相同的n

with n_cte as (
    select /*+ materialize*/ ntile(cnt) over ( partition by cnt order by Id ) NT, Id
    from tab
)
select  n.NT, phigh.Id 
from    (select distinct NT from n_cte) n 
outer apply (
    select * 
    from n_cte where n.NT = n_cte.NT and rownum = 1 order by Id
) low
outer apply (
    select * 
    from (select * from n_cte where n_cte.NT = n.NT order by Id desc) d where rownum = 1
) high
outer apply (
    select * 
    from (select * from n_cte where n_cte.NT = n.NT-1 order by Id desc) d where rownum = 1
) phigh

db<>fiddle demo

另一个选择是在cte部件内添加SELECT /*+ materialize*/ ...提示。

答案 1 :(得分:0)

我发现重命名high中共享的列名,并且'phigh`起作用。

with t as (
  select 10 as cnt, 1 as Id from dual
), 
x as (
    select ntile(cnt) over ( partition by cnt order by Id ) NT, Id
    from t
)
select  n.NT, 
        high.Id a, 
        phigh.Id
from    (select distinct NT from x) n 
        outer apply (select * from x where x.NT = n.NT and rownum = 1 order by Id) low
        outer apply (select Id z from (select * from x where x.NT = n.NT order by Id desc) d where rownum = 1) high
        outer apply (select * from (select * from x where x.NT = n.NT - 1 order by Id desc) d where rownum = 1) phigh

但这对我(问题所有者)来说真的不是解决方案。该代码将动态生成,并且会有很多列。

当多个子查询返回具有相同名称的列并且这些列在select子句中时,Oracle似乎有问题。

解决方案2:

outer apply (select * from x where x.NT = n.NT and rownum = 1 order by Id) low更改为outer apply (select * from x where x.NT = 1 and rownum = 1 order by Id) low也将消除该错误。