外连接超过1个表

Nat*_*ati 2 sql oracle outer-join

假设我有5个表,如下所示:

CREATE TABLE T1 (
FIRST_NAME VARCHAR2(100),
LAST_NAME VARCHAR2(100),
CITY NUMERIC,
SALARY NUMERIC);

CREATE TABLE T2 (
CITY NUMERIC,
DISTRICT  NUMERIC);

CREATE TABLE T3 (
DISTRICT NUMERIC,
DOMAIN NUMERIC);

CREATE TABLE T4 (
DOMAIN NUMERIC,
DETAILS_BOOK NUMERIC);

CREATE TABLE T5 (
DETAILS_BOOK NUMERIC,
FIRST_NAME VARCHAR2(100),
LAST_NAME VARCHAR2(100),
EMAIL VARCHAR2(100));

INSERT INTO T1 VALUES ('john', 'doe',1001,1000); 
INSERT INTO T1 VALUES ('jack', 'jill',1001,2000);
INSERT INTO T1 VALUES ('jeff', 'bush',1001,1500);

INSERT INTO T2 VALUES (1001,1);

INSERT INTO T3 VALUES (1,543);

INSERT INTO T4 VALUES (543,22);

INSERT INTO T5 VALUES (22,'john', 'doe','john@22.com');
INSERT INTO T5 VALUES (44,'john', 'doe','john@44.com');
INSERT INTO T5 VALUES (22,'jeff', 'bush','jeff@22.com');
INSERT INTO T5 VALUES (44,'jeff', 'bush','jeff@44.com');
Run Code Online (Sandbox Code Playgroud)

现在,我想要来自t1的所有记录,包括他们的工资和电子邮件,对应于表t2,t3和t4,这样reuslt应该是:

FIRST_NAME | LAST_NAME | SALARY | EMAIL
--------------------------------------------------
john       | doe       |  1000  | john@22.com
jeff       | bush      |  1500  | jeff@22.com
jack       | jill      |  2000  | (NULL)
Run Code Online (Sandbox Code Playgroud)

到目前为止我得到的是:

SELECT T1.FIRST_NAME, T1.LAST_NAME,T1.SALARY,T5.EMAIL
FROM T1,T2,T3,T4,T5
WHERE   T1.FIRST_NAME = T5.FIRST_NAME (+)
and     T1.LAST_NAME = T5.LAST_NAME(+)
AND     T1.CITY = T2.CITY
AND     T2.DISTRICT = T3.DISTRICT
AND     T3.DOMAIN = T4.DOMAIN
AND     T4.DETAILS_BOOK = T5.DETAILS_BOOK
Run Code Online (Sandbox Code Playgroud)

它只返回前两行.

Mah*_*mal 10

试试这个:

SELECT 
  T1.FIRST_NAME, 
  T1.LAST_NAME,
  T1.SALARY,
  T5.EMAIL
FROM T1
LEFT JOIN T2  ON T1.CITY         = T2.CITY
LEFT JOIN T3  ON T2.DISTRICT     = T3.DISTRICT
LEFT JOIN T4  ON T3.DOMAIN       = T4.DOMAIN
LEFT JOIN T5  ON T4.DETAILS_BOOK = T5.DETAILS_BOOK
             AND T1.FIRST_NAME   = T5.FIRST_NAME
             AND T1.LAST_NAME    = T5.LAST_NAME;
Run Code Online (Sandbox Code Playgroud)

SQL小提琴演示

这会给你:

| FIRST_NAME | LAST_NAME | SALARY |       EMAIL |
-------------------------------------------------
|       john |       doe |   1000 | john@22.com |
|       jeff |      bush |   1500 | jeff@22.com |
|       jack |      jill |   2000 |      (null) |
Run Code Online (Sandbox Code Playgroud)

问题是,使得你的连接INNER JOIN之后的OUTER JOIN工作就像一个INNER,因为,内部连接消除了来自外连接的那些不匹配的行.

请注意:我使用了ANSI SQL-92显式LEFT OUTER JOIN语法,而不是您在查询中使用的旧隐式OUTERINNER连接语法.

请尝试使用LEFT OUTER JOIN而不是旧的外连接语法,并避免INNER JOINOUTER JOINs 之后.

有关详细信息,请参阅:


更新:

FROM子句中有多个表引用时JOIN,每个表都与下一个表连​​接,从FROM1个句子开始,结果是临时结果集,然后这个临时结果集与下一个表连​​接,依此类推.如果是 OUTER JOIN,有左或右:

  • LEFT JOIN 将包括左表中那些不匹配的行,其中,
  • RIGHT JOIN 将包括右表中那些不匹配的行.

根据您要选择的数据,您必须在JOIN操作员的两侧以及它们的顺序中注意这些表.


1:这只是逻辑查询处理顺序,但实际顺序始终取决于查询优化器.