MySQL的Join使用
在MySQL(以5.1為例)中,表連線的語法可以參見MySQL官方手冊:MySQL官方手冊-JOIN
在查詢中,連線的語法類似
- SELECT select_expr FROM table_references
table_references(對錶的引用)的定義如下(也可以看成連線表示式):(暈暈暈哈)
- table_references:
- table_reference [, table_reference] ...
- table_reference:
- table_factor
- | join_table
- table_factor:
- tbl_name [[AS] alias] [index_hint_list]
- | table_subquery [AS] alias
- | ( table_references )
- | { OJ table_reference LEFT OUTER JOIN table_reference
- ON conditional_expr }
- join_table:
- table_reference [INNER | CROSS] JOIN table_factor [join_condition]
- | table_reference STRAIGHT_JOIN table_factor
- | table_reference STRAIGHT_JOIN table_factor ON conditional_expr
- | table_reference {LEFT|RIGHT} [OUTER] JOIN table_reference join_condition
- | table_reference NATURAL [{LEFT|RIGHT} [OUTER]] JOIN table_factor
- join_condition:
- ON conditional_expr
- | USING (column_list)
- index_hint_list:
- index_hint [, index_hint] ...
- index_hint:
- USE {INDEX|KEY}
- [{FOR {JOIN|ORDER BY|GROUP BY}] ([index_list])
- | IGNORE {INDEX|KEY}
- [{FOR {JOIN|ORDER BY|GROUP BY}] (index_list)
- | FORCE {INDEX|KEY}
- [{FOR {JOIN|ORDER BY|GROUP BY}] (index_list)
- index_list:
- index_name [, index_name] ...
其中,table_factor是基本的表選擇,而join_table是基於表的一些擴充套件。
下面,通過實驗介紹一下表連線。
首先,假設有以下幾個表
id | book |
---|---|
1 | java |
2 | c++ |
3 | php |
id | author |
---|---|
2 | zhang |
3 | wang |
4 | li |
author | year |
---|---|
zhang | 2003 |
ma | 2006 |
liu | 2011 |
Inner Join 內連線
將兩個表中存在連線關係的欄位,組成的記錄集,叫做內連線。
內連線等價於
- mysql> select table1.id as id,book,author from table1, table2 where table1.id=table2.id;
- +------+------+--------+
- | id | book | author |
- +------+------+--------+
- | 2 | c++ | zhang |
- | 3 | php | wang |
- +------+------+--------+
- 2 rows in set (0.00 sec)
- mysql> select * from table1 inner join table2 using (id);
- +------+------+--------+
- | id | book | author |
- +------+------+--------+
- | 2 | c++ | zhang |
- | 3 | php | wang |
- +------+------+--------+
- 2 rows in set (0.00 sec)
可以看出,兩者是等價的。沒有Using子句的Inner Join相當於是求兩個table的笛卡爾積。
Cross Join 交叉連線
在Mysql中,Cross Join可以用逗號表示式表示,例如(table1, table 2)。在Mysql中,Cross Join 和 Inner Join 是等價的,但是在標準SQL中,它們並不等價,Inner Join 用於帶有on表示式的連線,反之用Cross Join。以下兩個SQL語句是等價的。
Cross Join 指的是兩個table的笛卡爾積。以下三句SQL是等價的。
- mysql> select * from table1 inner join table2;
- mysql> select * from table1 cross join table2;
- mysql> select * from (table1, table2);
- mysql> select * from table1 nature join table2;
- 結果集:
- +------+------+------+--------+
- | id | book | id | author |
- +------+------+------+--------+
- | 1 | java | 2 | zhang |
- | 2 | c++ | 2 | zhang |
- | 3 | php | 2 | zhang |
- | 1 | java | 3 | wang |
- | 2 | c++ | 3 | wang |
- | 3 | php | 3 | wang |
- | 1 | java | 4 | li |
- | 2 | c++ | 4 | li |
- | 3 | php | 4 | li |
- +------+------+------+--------+
不難理解,下面兩句SQL也是等價的。
- mysql> select * from table1 left join (table2, table3) on (table2.id = table1.id and table2.author = table3.author);
- mysql> select * from table1 left join (table2 cross join table3) on (table2.id = table1.id and table2.author = table3.author);
- 結果集:
- +------+------+------+--------+--------+------+
- | id | book | id | author | author | year |
- +------+------+------+--------+--------+------+
- | 1 | java | NULL | NULL | NULL | NULL |
- | 2 | c++ | 2 | zhang | zhang | 2003 |
- | 3 | php | NULL | NULL | NULL | NULL |
- +------+------+------+--------+--------+------+
Natural Join 自然連線
NATURAL [LEFT] JOIN:這個句子的作用相當於INNER JOIN,或者是在USING子句中包含了聯結的表中所有公共欄位的Left JOIN(左聯結)。
也就是說:下面兩個SQL是等價的。
- mysql> select * from table1 natural join table2;
- mysql> select * from table1 inner join table2 using (id);
- 結果集:
- +------+------+--------+
- | id | book | author |
- +------+------+--------+
- | 2 | c++ | zhang |
- | 3 | php | wang |
- +------+------+--------+
同時,下面兩個SQL也是等價的。
- mysql> select * from table1 natural left join table2;
- mysql> select * from table1 left join table2 using(id);
- 結果集:
- +------+------+--------+
- | id | book | author |
- +------+------+--------+
- | 1 | java | NULL |
- | 2 | c++ | zhang |
- | 3 | php | wang |
- +------+------+--------+
Left Join 左外連線
左外連線A、B表的意思就是將表A中的全部記錄和表B中欄位連線形成的記錄集,這裡注意的是最後出來的記錄集會包括表A的全部記錄。
左連線表1,表二等價於右連線表二,表一。如下兩個SQL是等價的:
- mysql> select * from table1 left join table2 using (id);
- mysql> select * from table2 right join table1 using (id);
- 結果集:
- +------+------+--------+
- | id | book | author |
- +------+------+--------+
- | 1 | java | NULL |
- | 2 | c++ | zhang |
- | 3 | php | wang |
- +------+------+--------+
Right Join 右外連線
右外連線和左外連線是類似的。為了方便資料庫便於訪問,推薦使用左外連線代替右外連線。
1、兩個表求差集的方法
如果求 左表 - 右表 的差集,使用類似下面的SQL:
- SELECT left_tbl.* FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id WHERE right_tbl.id IS NULL;
- 例如
- mysql> select table1.* from table1 left join table2 using(id) where table2.id is null;
- +------+------+
- | id | book |
- +------+------+
- | 1 | java |
- +------+------+
- 1 row in set (0.00 sec)
2、Using子句
Using子句可以使用On子句重寫。但是使用Select * 查詢出的結果有差別。以下兩句話是等價的:
- mysql> select id, book, author from table1 join table2 using (id);
- mysql> select table1.id, book, author from table1 join table2 on table1.id=table2.id;
- 結果集:
- +------+------+--------+
- | id | book | author |
- +------+------+--------+
- | 2 | c++ | zhang |
- | 3 | php | wang |
- +------+------+--------+
但是下面兩個有些許不同,使用on時候,重複的部分會被輸出兩次。
- mysql> select * from table1 join table2 using (id);
- +------+------+--------+
- | id | book | author |
- +------+------+--------+
- | 2 | c++ | zhang |
- | 3 | php | wang |
- +------+------+--------+
- 2 rows in set (0.00 sec)
- mysql> select * from table1 join table2 on table1.id=table2.id;
- +------+------+------+--------+
- | id | book | id | author |
- +------+------+------+--------+
- | 2 | c++ | 2 | zhang |
- | 3 | php | 3 | wang |
- +------+------+------+--------+
- 2 rows in set (0.00 sec)
3、Straight Join的使用
STRAIGHT_JOIN 和 JOIN相似,除了大部分情況下,在使用STRAIGHT_JOIN時候,先讀右表後讀左表。而在大部分情況下是先讀左表的。STRAIGHT_JOIN僅用於少數情況下的表連線效能優化,比如右表記錄數目明顯少於左表。
4、Mysql表連線的運算順序
在MySQL 5.1版本中,INNER JOIN, CROSS JOIN, LEFT JOIN, 和RIGHT JOIN 比逗號表示式具有更高的優先順序。
因此SQL1被解析成SQL3,而不是SQL2。
- SQL1 : SELECT * FROM t1, t2 JOIN t3 ON (t1.i1 = t3.i3);
- SQL2 : SELECT * FROM (t1, t2) JOIN t3 ON (t1.i1 = t3.i3);
- SQL3 : SELECT * FROM t1, (t2 JOIN t3 ON (t1.i1 = t3.i3));
因此會報錯,找不到i1列。因此以後在寫這樣的查詢的時候,最好寫明白,不要省略括號,這樣能避免很多錯誤。
5、迴圈的自然連線
在MySQL 5.1版本中,SQL1等價於SQL3, 而在MySQL以前版本中,SQL1等價於SQL2。
- SQL1 : SELECT ... FROM t1 NATURAL JOIN t2 NATURAL JOIN t3;
- SQL2 : SELECT ... FROM t1, t2, t3 WHERE t1.b = t2.b AND t2.c = t3.c;
- SQL3 : SELECT ... FROM t1, t2, t3 WHERE t1.b = t2.b AND t2.c = t3.c AND t1.a = t3.a;
相關文章
- MySQL JOIN的使用MySql
- Mysql join 的本質,Nested Loop Join 和 Hash JoinMySqlOOP
- MySQL LEFT JOIN/ INNER JOIN/RIGHT JOINMySql
- mysql left join轉inner joinMySql
- MySQL的各種joinMySql
- mysql + left joinMySql
- MySQL Join BufferMySql
- MySQL Join語法MySql
- mysql join詳解MySql
- 深入理解mysql之left join 使用詳解MySql
- MySQL 的 join 功能弱爆了?MySql
- MySql的join(連線)查詢 (三表 left join 寫法)MySql
- MapReduce框架-Join的使用框架
- mysql的left join和inner join的效率對比,以及如何優化MySql優化
- 使用MySQL的遞延Join連線實現高效分頁 - AaronMySql
- MySQL Join的底層實現原理MySql
- Mysql實現全外部連線(mysql無法使用full join的解決辦法)MySql
- sql語句中JOIN ON 的使用SQL
- MySQL表關聯join方式MySql
- 我想說:mysql 的 join 真的很弱MySql
- MySQL系列6 - join語句的優化MySql優化
- MySQL筆記-左連線的使用(left join有關聯的多表查詢)MySql筆記
- MySQL中join語句的基本使用教程及其欄位對效能的影響MySql
- MySQL 之 LEFT JOIN 避坑指南MySql
- MySQL join連表查詢示例MySql
- mysql left join 優化學習MySql優化
- MySQL中的Join 的演算法(NLJ、BNL、BKA)MySql演算法
- sql中的join、left join、right joinSQL
- Hive JOIN使用詳解Hive
- MYSQL 怎麼 LEFT JOIN 多表聯查MySql
- MySQL INNER JOIN關聯多張表的寫法MySql
- 【轉載】為什麼 MySQL 不推薦使用子查詢和 joinMySql
- [轉載] 為什麼 MySQL 不推薦使用子查詢和 joinMySql
- Mysql資料庫使用from與join兩表查詢的方法區別總結MySql資料庫
- 【MySQL】MySQL效能優化之Block Nested-Loop Join(BNL)MySql優化BloCOOP
- sql之left join、right join、inner join的區別SQL
- hash join\nest loop join\sort merge join的實驗OOP
- sql的left join 、right join 、inner join之間的區別SQL