SELECT select_expression, select_expression, ... FROM table_reference JOIN table_reference JOIN table_reference, ... [ON join_condition]说明
SELECT select_expression, select_expression, ... FROM table_name JOIN table_name JOIN table_name, ...如果在JOIN子句中不指定连接条件,这样的连接就是笛卡尔连接。连接的结果是由被连接表中所有记录组成的有序数组(ordered tuples)。所以,笛卡尔连接输出的记录条数等于被连接表的记录条数的乘积。
[$host] transwarp> SELECT \* FROM join_demo1; 1 2 3 [$host] transwarp> SELECT \* FROM join_demo2; a b c d [$host] transwarp> SELECT \* FROM join_demo1 JOIN join_demo2; 1 a 1 b 1 c 1 d 2 a 2 b 2 c 2 d 3 a 3 b 3 c 3 d [$host] transwarp> SELECT count(\*) join_demo1 JOIN join_demo2; 12这样的表连接会产生大量的数据,而且并不经常具有意义,所以很少出现在实际应用中。大多数这样的表连接产生于没有加JOIN条件的错误。所以为了代码的清晰,如果真的需要进行笛卡尔积连接,最好使用专门的关键词CROSS JOIN:
SELECT table1.col1, table2.col2, ... FROM table1 CROSS JOIN table2
SELECT select_expression, select_expression, ... FROM table_refernce1 (JOIN|INNER JOIN) table_reference2 ON (table_reference1.column_1 = table_reference2.column_a)内连接只显示参与连接的表中有匹配的记录。JOIN和INNER JOIN在这里用法一样。
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)
假设我们有两张表,student_info和course_info。student_info包含了五个学生的名字和他们分别选修的课程编号:
transwarp> SELECT \* FROM student_info; 赵一 SCU100 钱二 MUS101 孙三 NULL 李四 COM101 周五 BIO101course_info包含了五门选修课的课程编号和课程名称:
transwarp> SELECT \* FROM course_info; BIO101 生物基础 COM101 面向对象编程 MUS101 西方古典音乐赏析 SCU100 雕塑 MAT100 微积分现在我们想要通过将两张表在课程编号匹配值处连接来查看学生选择的选修课课名:
[$host] transwarp> SELECT student_info.stu_name, course_info.course_name FROM student_info JOIN course_info ON (student_info.course_id = course_info.course_id); 赵一 雕塑 钱二 西方古典音乐赏析 李四 面向对象编程 周五 生物基础更多例子
[$host] transwarp> SELECT user_info.name, transactions.trans_id FROM user_info JOIN transactions ON (user_info.acc_num = transactions.acc_num); 马从筠 943197522 马从筠 499506900 马从筠 289018112 马从筠 895916502 马从筠 404905188 马从筠 213859826 祝韩恒 900192386 祝韩恒 952639648 华微 594819547 华微 817414815 魏向卉 929634984 魏向卉 209441379 魏向卉 719753265 魏向卉 597565609 邱坤 648230055 邱坤 975639131 邱坤 459590958 潘营泽 952110653 李韩瑶 991691937 管淑艳 162742112
SELECT select_expression, select_expression, ... FROM table_reference (LEFT|RIGHT|FULL) OUTER JOIN table reference左外连接:LEFT OUTER JOIN
[$host] transwarp> SELECT student_info.stu_name, course_info.course_name FROM student_info LEFT OUTER JOIN course_info ON (student_info.course_id = course_info.course_id); 赵一 雕塑 钱二 西方古典音乐赏析 孙三 NULL 李四 面向对象编程 周五 生物基础
右外连接:RIGHT OUTER JOIN
右外连接和左外连接相似,但是会将右边表(这里的course_info)中的所有记录返回:
[$host] transwarp> SELECT student_info.stu_name, course_info.course_name FROM student_info RIGHT OUTER JOIN course_info ON (student_info.course_id = course_info.course_id); 周五 生物基础 李四 面向对象编程 钱二 西方古典音乐赏析 赵一 雕塑 NULL 微积分全外连接:FULL OUTER JOIN
[$host] transwarp> SELECT student_info.stu_name, course_info.course_name FROM student_info FULL OUTER JOIN course_info ON (student_info.course_id = course_info.course_id); 周五 生物基础 赵一 雕塑 NULL 微积分 李四 面向对象编程 钱二 西方古典音乐赏析 孙三 NULL
SELECT table1.col1, table2.col2, ... FROM table1, table2 WHERE table1.col3 = table2.col1;隐式JOIN的命令中不含有JOIN...ON...关键词,而是通过WHERE子句作为连接条件将两张表连接。
[$host] transwarp> SELECT student_info.stu_name, course_info.course_name FROM student_info, course_info WHERE student_info.course_id = course_info.course_id; 赵一 雕塑 钱二 西方古典音乐赏析 李四 面向对象编程 周五 生物基础在连接和过滤都有的语句中,使用隐式JOIN会让人容易混淆哪些子句是用来连接的而哪些子句是用来过滤的。比如:
[$host] transwarp> SELECT name, trans_id FROM user_info, transactions WHERE user_info.acc_num = transactions.acc_num AND trans_time < 20140630235959; 马从筠 943197522 马从筠 499506900 马从筠 404905188 马从筠 213859826 祝韩恒 952639648 华微 817414815 魏向卉 929634984 魏向卉 209441379 魏向卉 719753265 魏向卉 597565609 邱坤 648230055 邱坤 975639131 邱坤 459590958 潘营泽 952110653
SELECT table1.col1, table1.col2, ... table2.col1, table2.col3, ... FROM table1 NATRUAL JOIN table2;使用NATURAL JOIN,用户可以不需要明确写出JOIN条件。Inceptor会自动在被连接的两张表中寻找名字相同的列。如果两张表table1和table2中存在同名列col1,Inceptor会自动生成JOIN条件
table1.col1=table2.col1。如果Inceptor在被连接的两张表中找不到同名列,Inceptor会将指令作为无条件的连接,也就是一个笛卡尔积。[$host] transwarp> SELECT name, trans_id from user_info NATURAL JOIN transactions; 邱坤 648230055 邱坤 975639131 邱坤 459590958 李韩瑶 991691937 管淑艳 162742112 马从筠 943197522 马从筠 499506900 马从筠 289018112 马从筠 895916502 马从筠 404905188 马从筠 213859826 华微 594819547 华微 817414815 魏向卉 929634984 魏向卉 209441379 魏向卉 719753265 魏向卉 597565609 潘营泽 952110653 祝韩恒 900192386 祝韩恒 952639648
SELECT select_expression, select_expression, ... FROM table_reference [(RIGHT|LEFT|FULL) OUTER] JOIN table_reference ON (join_condition) [(RIGHT|LEFT|FULL) OUTER] JOIN table_reference ON (join_condition) ...说明
[$host] transwarp> SELECT \* FROM lecturer_info; 石仲华 MAT101 李周 COM101 樊玲 MUS101 曹东海 SCU100 钱文 BIO101我们通过连接学生信息表,课程信息表和教师信息表来查看所有学生正在上的课和课程的教师
[$host] transwarp> SELECT stu_name, course_name, lecturer_name FROM student_info LEFT OUTER JOIN course_info ON (student_info.course_id = course_info.course_id)LEFT OUTER JOIN lecturer_info ON (course_info.course_id = lecturer_info.course_id); 赵一 雕塑 曹东海 钱二 西方古典音乐赏析 樊玲 孙三 NULL NULL 李四 面向对象编程 李周 周五 生物基础 钱文
SELECT t1.col1, tb1.col2, t2.col1, t3.col,...
FROM table1 t1 JOIN table2 t2
ON t1.col1 = t2.col1
INNER JOIN table3 t3
ON t2.col2 = t3.col1
INNER JOIN table1 tb1
ON t3.col = tb1.col2;
SELECT select_expression, select_expression, ... FROM table_reference alias1 JOIN table_reference alias2 ON (join_condition)举例
[$host] transwarp> SELECT \* FROM employee_info; 10817 张鑫叶 94832 20140509 13049 王明哲 94832 20140616 58290 许玮伦 12083 20120901 94832 戴李仁 12083 20111212 12083 郑希 56412 20110916 56412 吴思翼 NULL 20110916我们用这张表和自己连接来查询员工和他们上级的姓名:
[$host] transwarp> SELECT e.employee_name, sup.employee_name FROM employee_info e LEFT OUTER JOIN employee_info sup ON (e.sup_id = sup.employee_id); 张鑫叶 戴李仁 王明哲 戴李仁 许玮伦 郑希 戴李仁 郑希 郑希 吴思翼 吴思翼 NULL
SELECT select_expression, select_expression, ... FROM table_reference_1 LEFT SEMI JOIN table_reference_2 ON (join_condition)举例
[$host] transwarp> SELECT \* FROM test1; 1 a 1 b 1 c 2 a 3 e [$host] transwarp> SELECT \* FROM test2; 1 f 1 g 2 i下例我们分别用LEFT SEMI JOIN和在WHERE IN/EXISTS中嵌套子查询执行相同的任务:查看test1中的num列和test2.num匹配的所有记录。
[$host] transwarp> SELECT t1.num, t1.letter FROM test1 t1 LEFT SEMI JOIN test2 t2 ON t1.num = t2.num; 1 a 1 b 1 c 2 a使用在WHERE...IN中嵌套子查询
[$host] transwarp> SELECT t1.num, t1.letter FROM test1 t1 WHERE t1.num IN (SELECT t2.num FROM test2 t2); 1 a 1 b 1 c 2 a使用在WHERE EXISTS中嵌套子查询
[$host] transwarp> SELECT t1.num, t1.letter FROM test1 t1 WHERE EXISTS (SELECT 1 FROM test2 t2 WHERE t2.num = t1.num); 1 a 1 b 1 c 2 a举例
[$host] transwarp> SELECT t1.num, t1.letter FROM test1 t1 WHERE t1.num NOT IN (SELECT t2.num FROM test2 t2); 3 e在WHERE NOT EXISTS中嵌套子查询
[$host] transwarp> SELECT t1.num, t1.letter FROM test1 t1 WHERE NOT EXISTS (SELECT 1 FROM test2 t2 WHERE t1.num = t2.num); 3 e
不等价连接
到现在为止,我们只用到了等价连接(equi-join),也就是JOIN条件是一个等式。我们也可以将表不等价连接(non-equi join)。
语法
SELECT select_expression, select_expression, ... FROM table_reference1 JOIN table reference_2 ON equi_join_condition WHERE non_equi_join_condition从语法中我们看到,要执行不等价连接,ON子句中的连接条件必须是等价条件,不等价条件体现在WHERE子句中的过滤条件中。不等价连接和笛卡尔积相像,很容易返回大量结果(在两表行数乘积的级别),ON子句中要求有等价条件可以限制结果的数量。如果确定不需要限制结果数量,可以在ON子句中的等价条件里放一个永远成立的等式,比如1=1。执行这样的操作必须格外小心。
[$host] transwarp> SELECT e1.employee_name, e2.employee_name FROM employee_info e1 JOIN employee_info e2 ON 1 = 1 WHERE e1.employee_name <> e2.employee_name; 张鑫叶 王明哲 张鑫叶 许玮伦 张鑫叶 戴李仁 张鑫叶 郑希 张鑫叶 吴思翼 王明哲 张鑫叶 王明哲 许玮伦 王明哲 戴李仁 王明哲 郑希 王明哲 吴思翼 许玮伦 张鑫叶 许玮伦 王明哲 许玮伦 戴李仁 许玮伦 郑希 许玮伦 吴思翼 戴李仁 张鑫叶 戴李仁 王明哲 戴李仁 许玮伦 戴李仁 郑希 戴李仁 吴思翼 郑希 张鑫叶 郑希 王明哲 郑希 许玮伦 郑希 戴李仁 郑希 吴思翼 吴思翼 张鑫叶 吴思翼 王明哲 吴思翼 许玮伦 吴思翼 戴李仁 吴思翼 郑希这里join条件是
e1.name<> e2.id,因为一个人不能和自己比赛。这条指令会导致每个员工对都会重复一次,所以我们可以修改连接条件为e1.name > e2.name :
[$host] transwarp> SELECT e1.employee_name, e2.employee_name FROM employee_info e1 JOIN employee_info e2 ON 1 = 1 WHERE e1.employee_name > e2.employee_name; 张鑫叶 吴思翼 王明哲 张鑫叶 王明哲 戴李仁 王明哲 吴思翼 许玮伦 张鑫叶 许玮伦 王明哲 许玮伦 戴李仁 许玮伦 吴思翼 戴李仁 张鑫叶 戴李仁 吴思翼 郑希 张鑫叶 郑希 王明哲 郑希 许玮伦 郑希 戴李仁 郑希 吴思翼
SELECT /*+ MAPJOIN(b) */ select_expression, select_expression, ... FROM table_reference JOIN table_reference ON join_conditionInceptor已经有了自动MAP JOIN的功能,就是在有一张表在100MB一下时,Inceptor会自动执行MAP JOIN。所以用户可以无需特别指明使用MAP JOIN。如果在参与JOIN的表都较大时却指明使用MAP JOIN,可能会导致内存溢出。