【问题标题】:Oracle where clause outer joinOracle where 子句外连接
【发布时间】:2013-03-14 21:11:00
【问题描述】:

我无法理解如何使用特定查询的 where 子句进行外连接。我可以使用 JOIN 关键字完成连接。我要完成的查询是:
-- 在 books 表中显示所有图书的列表。如果客户订购了一本书,还请列出相应的订单号并说明客户来自

这是表结构

    desc customers
Name      Null     Type         
--------- -------- ------------ 
CUSTOMER# NOT NULL NUMBER(4)    
LASTNAME  NOT NULL VARCHAR2(10) 
FIRSTNAME NOT NULL VARCHAR2(10) 
ADDRESS            VARCHAR2(20) 
CITY               VARCHAR2(12) 
STATE              VARCHAR2(2)  
ZIP                VARCHAR2(5)  
REFERRED           NUMBER(4)    
REGION             CHAR(2)      
EMAIL              VARCHAR2(30) 

desc orders
Name       Null     Type         
---------- -------- ------------ 
ORDER#     NOT NULL NUMBER(4)    
CUSTOMER#           NUMBER(4)    
ORDERDATE  NOT NULL DATE         
SHIPDATE            DATE         
SHIPSTREET          VARCHAR2(18) 
SHIPCITY            VARCHAR2(15) 
SHIPSTATE           VARCHAR2(2)  
SHIPZIP             VARCHAR2(5)  
SHIPCOST            NUMBER(4,2)  

desc orderitems
Name     Null     Type         
-------- -------- ------------ 
ORDER#   NOT NULL NUMBER(4)    
ITEM#    NOT NULL NUMBER(2)    
ISBN              VARCHAR2(10) 
QUANTITY NOT NULL NUMBER(3)    
PAIDEACH NOT NULL NUMBER(5,2)  

desc books
Name     Null     Type         
-------- -------- ------------ 
ISBN     NOT NULL VARCHAR2(10) 
TITLE             VARCHAR2(30) 
PUBDATE           DATE         
PUBID             NUMBER(2)    
COST              NUMBER(5,2)  
RETAIL            NUMBER(5,2)  
DISCOUNT          NUMBER(4,2)  
CATEGORY          VARCHAR2(12) 

使用 join 我可以通过以下方式显示我认为正确的结果:

SELECT b.title, c.state, order#
FROM customers c JOIN orders o USING (customer#)
JOIN orderitems oi USING (order#)
RIGHT OUTER JOIN books b USING (isbn);


TITLE                          STATE     ORDER#
------------------------------ ----- ----------
HOW TO GET FASTER PIZZA                         
THE WOK WAY TO COOK                             
REVENGE OF MICKEY              MI          1012 
REVENGE OF MICKEY              GA          1019 
REVENGE OF MICKEY              WA          1009 
REVENGE OF MICKEY              TX          1014 
BODYBUILD IN 10 MINUTES A DAY  FL          1003 
HANDCRANKED COMPUTERS          MI          1012 
SHORTEST POEMS                 GA          1005 
PAINLESS CHILD-REARING         GA          1001 
PAINLESS CHILD-REARING         NJ          1004 
PAINLESS CHILD-REARING         FL          1016 
PAINLESS CHILD-REARING         MI          1012 
PAINLESS CHILD-REARING         GA          1011 
COOKING WITH MUSHROOMS         WY          1020 
COOKING WITH MUSHROOMS         ID          1008 
COOKING WITH MUSHROOMS         FL          1003 
COOKING WITH MUSHROOMS         WA          1000 
COOKING WITH MUSHROOMS         WA          1009 
COOKING WITH MUSHROOMS         FL          1018 
COOKING WITH MUSHROOMS         NJ          1015 
HOLY GRAIL OF ORACLE           TX          1007 
BUILDING A CAR WITH TOOTHPICKS                  
BIG BEAR AND LITTLE DOVE       FL          1017 
BIG BEAR AND LITTLE DOVE       TX          1007 
BIG BEAR AND LITTLE DOVE       MI          1012 
DATABASE IMPLEMENTATION        IL          1002 
DATABASE IMPLEMENTATION        TX          1007 
DATABASE IMPLEMENTATION        FL          1003 
DATABASE IMPLEMENTATION        WY          1013 
DATABASE IMPLEMENTATION        FL          1018 
DATABASE IMPLEMENTATION        NJ          1010 
HOW TO MANAGE THE MANAGER      GA          1001 
E-BUSINESS THE EASY WAY        TX          1007 
E-BUSINESS THE EASY WAY        FL          1006 

 35 rows selected 

这是我为 where 子句加入所尝试的:

-- using where clause
SELECT b.title,  c.state, oi.order#
FROM customers c, orders o, orderitems oi, books b
WHERE c.customer# = o.customer#
AND o.order# = oi.order#
AND oi.isbn(+) = b.isbn;

但是当我执行此查询时,我得到以下信息

TITLE                          STATE     ORDER#
------------------------------ ----- ----------
BODYBUILD IN 10 MINUTES A DAY  FL          1003 
REVENGE OF MICKEY              GA          1019 
REVENGE OF MICKEY              TX          1014 
REVENGE OF MICKEY              MI          1012 
REVENGE OF MICKEY              WA          1009 
DATABASE IMPLEMENTATION        FL          1018 
DATABASE IMPLEMENTATION        WY          1013 
DATABASE IMPLEMENTATION        NJ          1010 
DATABASE IMPLEMENTATION        TX          1007 
DATABASE IMPLEMENTATION        FL          1003 
DATABASE IMPLEMENTATION        IL          1002 
COOKING WITH MUSHROOMS         WY          1020 
COOKING WITH MUSHROOMS         FL          1018 
COOKING WITH MUSHROOMS         NJ          1015 
COOKING WITH MUSHROOMS         WA          1009 
COOKING WITH MUSHROOMS         ID          1008 
COOKING WITH MUSHROOMS         FL          1003 
COOKING WITH MUSHROOMS         WA          1000 
HOLY GRAIL OF ORACLE           TX          1007 
HANDCRANKED COMPUTERS          MI          1012 
E-BUSINESS THE EASY WAY        TX          1007 
E-BUSINESS THE EASY WAY        FL          1006 
PAINLESS CHILD-REARING         FL          1016 
PAINLESS CHILD-REARING         MI          1012 
PAINLESS CHILD-REARING         GA          1011 
PAINLESS CHILD-REARING         NJ          1004 
PAINLESS CHILD-REARING         GA          1001 
BIG BEAR AND LITTLE DOVE       FL          1017 
BIG BEAR AND LITTLE DOVE       MI          1012 
BIG BEAR AND LITTLE DOVE       TX          1007 
HOW TO MANAGE THE MANAGER      GA          1001 
SHORTEST POEMS                 GA          1005 

 32 rows selected

这里是一个 sql 链接,如果需要,它将构建结构https://www.dropbox.com/s/7tpbpz1hbufj3qn/JLDB_Build_8.sql

我很难弄清楚我做错了什么/与 where 子句连接不同。任何帮助或方向表示赞赏。 谢谢。

【问题讨论】:

    标签: oracle oracle11g


    【解决方案1】:

    当使用连接时,我建议使用显式左/右连接。比如……

    Select A.*, B.*, C.*
    from TableA A 
     left outer join TableB B
     on A.field1 = B.fkfield1
     and A.field2 0 B.fkfield2
     ...
    
     left outer join TableC C
     on A.field1 = C.fkfield1
     and A.field2 0 C.fkfield2
     ...
    

    在这种情况下,表 A 的记录将与表 B 上的记录匹配。如果表 B 上没有匹配项,则表 B 中的列将为空。第二个连接的工作方式与第一个类似,如果表 C 中的字段 1(在表 A 上)没有匹配值,则这种情况也会显示 null,fkfield1。

    另一方面,如果您需要匹配第二个表而不是第一个表的所有记录,则需要执行“内连接”。只需将上面示例中的“左外连接”替换为“内连接”即可。

    谢谢!

    @leo

    【讨论】:

      【解决方案2】:

      试试这个:

      SELECT b.title,  o.state, o.order#
      FROM books b
      , (select o.order#, oi.isbn, o.customer#, c.state
         from orders o, orderitems oi, customers c
         where o.order# = oi.order#
         and   c.customer# = o.customer#
      ) o
      WHERE 
      AND o.isbn(+) = b.isbn;
      

      【讨论】:

      • 非常感谢它的工作原理并获得与 JOIN 查询相同的结果。没有嵌套选择有没有办法做到这一点?我能够在没有客户表的情况下获得相同的结果,所以这似乎与我如何将所有内容与客户表连接起来。 SELECT b.title, oi.order# FROM orders o, orderitems oi, books b WHERE oi.isbn(+) = b.isbn AND o.order# = oi.order#;
      • 嗯,我想我明白了,但不确定我是否完全理解。我能够使它与以下内容一起工作:SELECT b.title, c.state, o.order# FROM customers c, orders o, orderitems oi, books b WHERE c.customer#(+) = o.customer# AND o.order#(+) = oi.order# AND oi.isbn(+) = b.isbn; 显然,您需要对每个表进行外连接,以使外连接在 where 子句中正常工作。
      【解决方案3】:

      我在更多挖掘之后发现了这个

      这是来自http://docs.oracle.com/cd/B19306_01/server.102/b14200/queries006.htm

      如果 A 和 B 由多个连接条件连接,则必须使用 所有这些条件中的 (+) 运算符。如果你不这样做,那么 Oracle 数据库将只返回从简单的 加入,但没有警告或错误提示您不加入 有外部连接的结果。

      如果您指定一个外连接,则 (+) 运算符不会产生外连接 外部查询中的表和内部查询中的另一个表。

      我能够通过以下方式让它工作:

      SELECT b.title, c.state, o.order# FROM customers c, orders o, orderitems oi, books b WHERE c.customer#(+) = o.customer# AND o.order#(+) = oi.order# AND oi.isbn(+) = b.isbn;

      【讨论】:

        猜你喜欢
        • 2013-08-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-05
        • 2023-03-31
        • 2023-03-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多