我在Oracle-12c中有一个模式,类似于一个包含帐户,帖子和评论的典型论坛.我正在编写一个查询来获取…
>一个用户
>所有用户的帖子
>对每个帖子的评论
>和每个评论的作者.
查询如下所示:
select "accounts".*,"p".*,"c".*,"author".* from "accounts" cross apply ( select * from "posts" where "posts"."author_id" = "accounts"."id" ) "p" cross apply ( select * from "comments" where "comments"."post_id" = "p"."id" ) "c" left join "accounts" "author" on "author"."id" = "c"."author_id" where "accounts"."id" = 1
此查询按预期工作.我正在使用CROSS APPLY而不是典型的JOIN,因为稍后我将添加OFFSET和FETCH以进行分页.但是,问题是CROSS APPLY省略了没有评论的帖子,这是我不想要的.我想在结果中保留帖子,即使他们没有评论.
所以我尝试将CROSS APPLY更改为OUTER APPLY.
select "accounts".*,"author".* from "accounts" outer apply ( select * from "posts" where "posts"."author_id" = "accounts"."id" ) "p" outer apply ( select * from "comments" where "comments"."post_id" = "p"."id" ) "c" left join "accounts" "author" on "author"."id" = "c"."author_id" where "accounts"."id" = 1
但是现在我收到了这个错误:
ORA-00904: "p"."id": invalid identifier 00904. 00000 - "%s: invalid identifier" *Cause: *Action: Error at Line: 9 Column: 34
出于某种原因,我的第二个OUTER APPLY join抱怨我引用第一个结果中的“p”.“id”.但是当我使用CROSS APPLY时它很好.
到底是怎么回事?为什么这些之间的行为存在差异?
编辑:在这个基本示例中似乎没有必要使用OUTER APPLY.这是从一个更复杂的场景中提炼出来的,我必须坚持认为外部应用确实是必要的,但是这个场景的细节与我所问的实际问题无关 – 这与CROSS和CROSS之间看似无证的行为差异有关.外部申请.
编辑:
Oracle版本:Database 12c标准版12.1.0.2.0版 – 64位生产
客户端:Oracle sql Developer版本4.2.0.16.356
服务器:uname的输出-a – Linux ubuntu-1gb-sfo2-01 4.4.0-64-generic#85-Ubuntu SMP Mon Feb 20 11:50:30 UTC 2017 x86_64 x86_64 x86_64 GNU / Linux
DDL:link
解决方法
至于
CodeFuller’s回答,我只想补充一点(A)有一个可用于此bug的补丁和(B)有一个可在12.1.0.2中运行的解决方法,但我不知道它是否能满足您的需求.
解决方法是基本嵌套连接,如下所示:
SELECT accounts.*,p.*,author.* FROM accounts CROSS APPLY (SELECT posts.id,posts.author_id,posts.text,comments.comment_author_id,comments.comment_text FROM posts OUTER APPLY (SELECT comments.author_id comment_author_id,comments.text comment_text FROM comments WHERE comments.post_id = posts.id) comments WHERE posts.author_id = accounts.id) p LEFT JOIN accounts author ON author.id = p.comment_author_id WHERE accounts.id = 1; ID NAME ID_1 AUTHOR_ID TEXT COMMENT_AUTHOR_ID COMMENT_TEXT ID_2 NAME_1 ---- --------- ---- --------- ------------------------------------------------- ----------------- --------------------------------------- ----- ------------------- 1 Fred 1 1 Fred wrote this and it has comments 3 This is Helen's comment on Fred's post 3 Helen 1 Fred 2 1 Fred wrote this and it does not have any comments -------- End of Data -------- 2 row(s) fetched
参考:表DDL的变通方法
CREATE TABLE accounts ( id NUMBER PRIMARY KEY,name VARCHAR2 (30) ); CREATE TABLE posts ( id NUMBER PRIMARY KEY,author_id NUMBER,text VARCHAR2 (240) ); CREATE TABLE comments ( id NUMBER PRIMARY KEY,post_id NUMBER,text VARCHAR2 (240) ); INSERT INTO accounts (id,name) VALUES (1,'Fred'); INSERT INTO accounts (id,name) VALUES (2,'Mary'); INSERT INTO accounts (id,name) VALUES (3,'Helen'); INSERT INTO accounts (id,name) VALUES (4,'Iqbal'); INSERT INTO posts (id,author_id,text) VALUES (1,1,'Fred wrote this and it has comments'); INSERT INTO posts (id,text) VALUES (2,'Fred wrote this and it does not have any comments'); INSERT INTO posts (id,text) VALUES (3,4,'Iqbal wrote this and it does not have any comments'); INSERT INTO comments (id,post_id,3,'This is Helen''s comment on Fred''s post');