sql – 使用`CROSS APPLY`和`OUTER APPLY`的行为不一致

前端之家收集整理的这篇文章主要介绍了sql – 使用`CROSS APPLY`和`OUTER APPLY`的行为不一致前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我在Oracle-12c中有一个模式,类似于一个包含帐户,帖子和评论的典型论坛.我正在编写一个查询获取

>一个用户
>所有用户的帖子
>对每个帖子的评论
>和每个评论的作者.

查询如下所示:

  1. select "accounts".*,"p".*,"c".*,"author".*
  2. from "accounts"
  3. cross apply (
  4. select * from "posts"
  5. where "posts"."author_id" = "accounts"."id"
  6. ) "p"
  7. cross apply (
  8. select * from "comments"
  9. where "comments"."post_id" = "p"."id"
  10. ) "c"
  11. left join "accounts" "author" on "author"."id" = "c"."author_id"
  12. where "accounts"."id" = 1

查询按预期工作.我正在使用CROSS APPLY而不是典型的JOIN,因为稍后我将添加OFFSET和FETCH以进行分页.但是,问题是CROSS APPLY省略了没有评论的帖子,这是我不想要的.我想在结果中保留帖子,即使他们没有评论.

所以我尝试将CROSS APPLY更改为OUTER APPLY.

  1. select "accounts".*,"author".*
  2. from "accounts"
  3. outer apply (
  4. select * from "posts"
  5. where "posts"."author_id" = "accounts"."id"
  6. ) "p"
  7. outer apply (
  8. select * from "comments"
  9. where "comments"."post_id" = "p"."id"
  10. ) "c"
  11. left join "accounts" "author" on "author"."id" = "c"."author_id"
  12. where "accounts"."id" = 1

但是现在我收到了这个错误

  1. ORA-00904: "p"."id": invalid identifier
  2. 00904. 00000 - "%s: invalid identifier"
  3. *Cause:
  4. *Action:
  5. 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中运行的解决方法,但我不知道它是否能满足您的需求.

解决方法是基本嵌套连接,如下所示:

  1. SELECT accounts.*,p.*,author.*
  2. FROM accounts
  3. CROSS APPLY (SELECT posts.id,posts.author_id,posts.text,comments.comment_author_id,comments.comment_text
  4. FROM posts
  5. OUTER APPLY (SELECT comments.author_id comment_author_id,comments.text comment_text
  6. FROM comments
  7. WHERE comments.post_id = posts.id) comments
  8. WHERE posts.author_id = accounts.id) p
  9. LEFT JOIN accounts author
  10. ON author.id = p.comment_author_id
  11. WHERE accounts.id = 1;
  12.  
  13.  
  14. ID NAME ID_1 AUTHOR_ID TEXT COMMENT_AUTHOR_ID COMMENT_TEXT ID_2 NAME_1
  15. ---- --------- ---- --------- ------------------------------------------------- ----------------- --------------------------------------- ----- -------------------
  16. 1 Fred 1 1 Fred wrote this and it has comments 3 This is Helen's comment on Fred's post 3 Helen
  17. 1 Fred 2 1 Fred wrote this and it does not have any comments
  18. -------- End of Data --------
  19. 2 row(s) fetched

参考:表DDL的变通方法

  1. CREATE TABLE accounts
  2. (
  3. id NUMBER PRIMARY KEY,name VARCHAR2 (30)
  4. );
  5.  
  6. CREATE TABLE posts
  7. (
  8. id NUMBER PRIMARY KEY,author_id NUMBER,text VARCHAR2 (240)
  9. );
  10.  
  11. CREATE TABLE comments
  12. (
  13. id NUMBER PRIMARY KEY,post_id NUMBER,text VARCHAR2 (240)
  14. );
  15.  
  16. INSERT INTO accounts (id,name)
  17. VALUES (1,'Fred');
  18.  
  19. INSERT INTO accounts (id,name)
  20. VALUES (2,'Mary');
  21.  
  22. INSERT INTO accounts (id,name)
  23. VALUES (3,'Helen');
  24.  
  25. INSERT INTO accounts (id,name)
  26. VALUES (4,'Iqbal');
  27.  
  28. INSERT INTO posts (id,author_id,text)
  29. VALUES (1,1,'Fred wrote this and it has comments');
  30.  
  31. INSERT INTO posts (id,text)
  32. VALUES (2,'Fred wrote this and it does not have any comments');
  33.  
  34. INSERT INTO posts (id,text)
  35. VALUES (3,4,'Iqbal wrote this and it does not have any comments');
  36.  
  37. INSERT INTO comments (id,post_id,3,'This is Helen''s comment on Fred''s post');

猜你在找的MsSQL相关文章