如何将使用外部表别名的 Top 1 子查询转换为 Oracle?

ber*_*d_k 4 oracle subquery

我有以下 SQL Server 查询

select
    (select top 1 b2 from  BB b where b.b1 = a.a1 order by b2) calc,
    a1,
    a2
from AA a
where a2 = 2;
Run Code Online (Sandbox Code Playgroud)

我可以使用解析函数重写

select
    (select b2 from 
    (select 
        row_number() over (order by b2) lfd, 
     b2 from  BB b where b.b1 = a.a1
    ) as t where lfd = 1
    ) calc,
    a1,
    a2
from AA a
where a2 = 2;
Run Code Online (Sandbox Code Playgroud)

但是当我将其转换为 oracle 时

create table AA ( a1 NUMBER(10), a2 NUMBER(10) );
insert into AA values ( 1, 1);
insert into AA values ( 1, 2);
insert into AA values ( 1, 3);
insert into AA values ( 2, 2);

create table BB ( b1 NUMBER(10), b2 NUMBER(10) );
insert into BB values ( 1, 1);
insert into BB values ( 2, 4);
insert into BB values ( 2, 5);


select * from AA;
select * from BB;


select
    (select b2 from 
    (select 
        row_number() over (order by b2) lfd, 
     b2 from  BB b where b.b1 = a.a1
    )  where lfd = 1
    ) calc,
    a1,
    a2
from AA a
where a2 = 2;
Run Code Online (Sandbox Code Playgroud)

我收到以下错误

Error at line 5
ORA-00904: "A"."A1": invalid column name
Run Code Online (Sandbox Code Playgroud)

Vin*_*rat 6

您将首先在 Oracle 中执行连接:

SELECT a1, a2, b2
  FROM (SELECT a1, a2, b2, 
               row_number() over(PARTITION BY a.a1 ORDER BY b.b2) lfd
           FROM AA a
           LEFT JOIN BB b ON b.b1 = a.a1
          WHERE a2 = 2)
 WHERE lfd = 1
Run Code Online (Sandbox Code Playgroud)

您的查询的问题在于,目前 Oracle 中的子查询无法访问来自父查询的值超过两级。

您还可以使用包含内部 SELECT 的 PL/SQL 函数。

  • [Asktom 上的这篇文章](http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1853075500346799932) 声称该限制是 ANSI SQL 规范的一部分。 (2认同)