ORACLE JOIN
- 条件连接(join)
- T1 { [INNER] | { LEFT | RIGHT | FULL } [OUTER] } JOIN T2 ON boolean_expression
- T1 { [INNER] | { LEFT | RIGHT | FULL } [OUTER] } JOIN T2 USING ( join column list )
- T1 NATURAL { [INNER] | { LEFT | RIGHT | FULL } [OUTER] } JOIN T2
- INNER 和 OUTER 对所有连接(join) 类型都是可选的.INNER 是缺省; LEFT,RIGHT,和 FULL 隐含外连接.
- 连接条件在ON或USING子句里声明, 或者用关键字NATURAL隐含地声明.连接条件判断来自两个源表 中的那些行是"匹配"的,这些我们将在下面详细解释.
- ON子句是最常见的连接条件的类型∶它接收一个和WHERE子句里用的一样的 布尔值表达式.如果两个分别来自T1和T2的行在ON表达式上运算的 结果为真,那么它们就算是匹配的行.
- USING是缩写的概念∶它接收一个用逗号分隔的字段名字列表, 这些字段必须是连接表共有的,最终形成一个连接条件,表示 这些字段对必须相同.最后,JOIN USING 的输出会为每一对相等 的输入字段输出一个字段,后面跟着来自各个表的所有其它字段. 因此,USING (a, b, c) 等效于 ON (t1.a = t2.a AND t1.b = t2.b AND t1.c = t2.c) 只不过是如果使用了ON,那么在结果里 a,b,和 c字段每个都会有两个, 而用USING的时候每个字段就只会有一个.
- 最后,NATURAL 是USING 的缩写形式∶它形成一个 USING 列表, 该列表由那些在两个表里都出现了的字段名字组成.和USING一样, 这些字段只在输出表里出现一次.
- 条件JOIN的可能类型是∶
- INNER JOIN
- 对于 T1 的每一行 R1,生成的连接表都有一行对应 T2 中的 每一个满足和 R1 的连接条件的行.
- LEFT OUTER JOIN
- 首先,执行一次内连接.然后,为 T1 里那些和 T2 里任何一行都不满足连接条件的行返回一个连接行, 同时该连接行里对应 T2 的列用空值补齐.因此, 生成的连接表里无条件地包含来自 T1 里的每一行至少 一个副本.
- RIGHT OUTER JOIN
- 首先,执行一次内连接.然后,为 T2 里那些和 T1 里任何一行都不满足连接条件的行返回一个连接行, 同时该连接行里对应 T1 的列用空值补齐.因此, 生成的连接表里无条件地包含来自 T2 里的每一行.
- FULL OUTER JOIN
- 首先,执行一次内连接.然后,为 T1 里那些和 T2 里任何一行都不满足连接条件的行返回一个连接行, 同时该连接行里对应 T2 的列用空值补齐. 同样,为 T2 里那些和 T1 里的任何行都不满足连接条件的 行返回一个连接行,该行里对应 T1 的列用空值补齐.
- 如果 T1 和 T2 有一个或者都是可以连接(join)的表, 那么所有类型的连接都可以串在一起或嵌套在一起. 你可以在JOIN子句周围使用圆括弧来控制连接顺序, 如果没有圆括弧,那么JOIN子句是从左向右嵌套的.
- 为了解释这些问题,假设我们有一个表 t1
- num | name
- -----+------
- 1 | a
- 2 | b
- 3 | c
- 和 t2
- num | value
- -----+-------
- 1 | xxx
- 3 | yyy
- 5 | zzz
- 然后我们用不同的连接方式可以获得各种结果:
- => SELECT * FROM t1 CROSS JOIN t2;
- num | name | num | value
- -----+------+-----+-------
- 1 | a | 1 | xxx
- 1 | a | 3 | yyy
- 1 | a | 5 | zzz
- 2 | b | 1 | xxx
- 2 | b | 3 | yyy
- 2 | b | 5 | zzz
- 3 | c | 1 | xxx
- 3 | c | 3 | yyy
- 3 | c | 5 | zzz
- (9 rows)
- => SELECT * FROM t1 INNER JOIN t2 ON t1.num = t2.num;
- num | name | num | value
- -----+------+-----+-------
- 1 | a | 1 | xxx
- 3 | c | 3 | yyy
- (2 rows)
- => SELECT * FROM t1 INNER JOIN t2 USING (num);
- num | name | value
- -----+------+-------
- 1 | a | xxx
- 3 | c | yyy
- (2 rows)
- => SELECT * FROM t1 NATURAL INNER JOIN t2;
- num | name | value
- -----+------+-------
- 1 | a | xxx
- 3 | c | yyy
- (2 rows)
- => SELECT * FROM t1 LEFT JOIN t2 ON t1.num = t2.num;
- num | name | num | value
- -----+------+-----+-------
- 1 | a | 1 | xxx
- 2 | b | |
- 3 | c | 3 | yyy
- (3 rows)
- => SELECT * FROM t1 LEFT JOIN t2 USING (num);
- num | name | value
- -----+------+-------
- 1 | a | xxx
- 2 | b |
- 3 | c | yyy
- (3 rows)
- => SELECT * FROM t1 RIGHT JOIN t2 ON t1.num = t2.num;
- num | name | num | value
- -----+------+-----+-------
- 1 | a | 1 | xxx
- 3 | c | 3 | yyy
- | | 5 | zzz
- (3 rows)
- => SELECT * FROM t1 FULL JOIN t2 ON t1.num = t2.num;
- num | name | num | value
- -----+------+-----+-------
- 1 | a | 1 | xxx
- 2 | b | |
- 3 | c | 3 | yyy
- | | 5 | zzz
- (4 rows)
- 用 ON 声明的连接条件也可以包含与连接不直接相关 的条件。这种功能可能对某些查询很有用,但是需要我们仔细想想。 比如:
- => SELECT * FROM t1 LEFT JOIN t2 ON t1.num = t2.num AND t2.value = 'xxx';
- num | name | num | value
- -----+------+-----+-------
- 1 | a | 1 | xxx
- 2 | b | |
- 3 | c | |
- (3 rows)