1. 程式人生 > >mysql中left join,right join,inner join,outer join 用法詳解

mysql中left join,right join,inner join,outer join 用法詳解

非常慚愧用了這麼久的mysql居然沒有用過outer join和inner join,對outer join的認識也僅是知道它是外連結,至於什麼用途都不清楚,至於還有沒有left outer join更是不得而知,某天有人問起,才想起自己mysql知識的貧乏,趕緊找了一下網上的left join,right join,inner join,outer join的用法來學習一下

下面是例子分析

表A記錄如下:
aID aNum
1 a20050111
2 a20050112
3 a20050113
4 a20050114
5 a20050115
表B記錄如下:
bID bName
1 2006032401
2 2006032402
3 2006032403
4 2006032404
8 2006032408
建立這兩個表SQL語句如下:
CREATE TABLE a
aID int( 1 ) AUTO_INCREMENT PRIMARY KEY ,
aNum char( 20 )
)
CREATE TABLE b(
bID int( 1 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
bName char( 20 )
)
INSERT INTO a
VALUES ( 1, 'a20050111' ) , ( 2, 'a20050112' ) , ( 3, 'a20050113' ) , ( 4, 'a20050114' ) , ( 5, 'a20050115' ) ;
INSERT INTO b
VALUES ( 1, ' 2006032401' ) , ( 2, '2006032402' ) , ( 3, '2006032403' ) , ( 4, '2006032404' ) , ( 8, '2006032408' ) ;
實驗如下:
1.left join(左聯接)
sql語句如下:
SELECT * FROM a
LEFT JOIN b
ON a.aID =b.bID
結果如下:
aID aNum bID bName
1 a20050111 1 2006032401
2 a20050112 2 2006032402
3 a20050113 3 2006032403
4 a20050114 4 2006032404
5 a20050115 NULL NULL
(所影響的行數為 5 行)
結果說明:
left join是以A表的記錄為基礎的,A可以看成左表,B可以看成右表,left join是以左表為準的.
換句話說,左表(A)的記錄將會全部表示出來,而右表(B)只會顯示符合搜尋條件的記錄(例子中為: A.aID = B.bID).
B表記錄不足的地方均為NULL.
2.right join(右聯接)
sql語句如下:
SELECT * FROM a
RIGHT JOING b
ON a.aID = b.bID
結果如下:
aID aNum bID bName
1 a20050111 1 2006032401
2 a20050112 2 2006032402
3 a20050113 3 2006032403
4 a20050114 4 2006032404
NULL NULL 8 2006032408
(所影響的行數為 5 行)
結果說明:
仔細觀察一下,就會發現,和left join的結果剛好相反,這次是以右表(B)為基礎的,A表不足的地方用NULL填充.
3.inner join(相等聯接或內聯接)
sql語句如下:
SELECT * FROM a
INNER JOIN b
ON a.aID =b.bID
等同於以下SQL句:
SELECT *
FROM a,b
WHERE a.aID = b.bID
結果如下:
aID aNum bID bName
1 a20050111 1 2006032401
2 a20050112 2 2006032402
3 a20050113 3 2006032403
4 a20050114 4 2006032404
結果說明:
很明顯,這裡只顯示出了 A.aID = B.bID的記錄.這說明inner join並不以誰為基礎,它只顯示符合條件的記錄.
LEFT JOIN操作用於在任何的 FROM 子句中,
組合來源表的記錄。使用 LEFT JOIN 運算來建立一個左邊外部聯接。左邊外部聯接將包含了從第一個(左邊)開始的兩個表中的全部記錄,即
使在第二個(右邊)表中並沒有相符值的記錄。
語法:FROM table1 LEFT JOIN table2 ON table1.field1 compopr table2.field2
說明:table1, table2引數用於指定要將記錄組合的表的名稱。
field1, field2引數指定被聯接的欄位的名稱。且這些欄位必須有相同的資料型別及包含相同型別的資料,但它們不需要有相同的
名稱。
compopr引數指定關係比較運算子:"=", "<", ">", "<=", ">=" 或 "<>"。
如果在INNER JOIN操作中要聯接包含Memo 資料型別或 OLE Object 資料型別資料的欄位,將會發生錯誤。

MySQL中的各種JOIN

1. 笛卡爾積(交叉連線)
在MySQL中可以為CROSS JOIN或者省略CROSS即JOIN,或者使用',' 

SELECT * FROM table1 CROSS JOIN table2 
SELECT * FROM table1 JOIN table2
SELECT * FROM table1,table2

由於其返回的結果為被連線的兩個資料表的乘積,因此當有WHERE, ON或USING條件的時候一般不建議使用,因為當資料表專案太多的時候,會非常慢。
一般使用LEFT [OUTER] JOIN或者RIGHT [OUTER] JOIN 

2. 內連線INNER JOIN

在MySQL中把INNER JOIN叫做等值連線,即需要指定等值連線條件
在MySQL中CROSS和INNER JOIN被劃分在一起,不明白。
參看MySQL幫助手冊
http://dev.mysql.com/doc/refman/5.0/en/join.html
join_table:
    table_reference [INNER | CROSS] JOIN table_factor [join_condition]

3. MySQL中的外連線,分為左外連線和右連線,
即除了返回符合連線條件的結果之外,還要返回左表(左連線)或者右表(右連線)中不符合連線條件的結果,相對應的使用NULL對應。

a. LEFT [OUTER] JOIN 
SELECT column_name FROM table1 LEFT [OUTER] JOIN table2 ON table1.column=table2.column
除了返回符合連線條件的結果之外,還需要顯示左表中不符合連線條件的資料列,相對應使用NULL對應

b. RIGHT [OUTER] JOIN
SELECT column_name FROM table1 RIGHT [OUTER] JOIN table2 ON table1.column=table2.column
RIGHT與LEFT JOIN相似不同的僅僅是除了顯示符合連線條件的結果之外,還需要顯示右表中不符合連線條件的資料列,相應使用NULL對應


--------------------------------------------
新增顯示條件WHERE, ON, USING

1. WHERE子句
2. ON
3. USING子句,如果連線的兩個表連線條件的兩個列具有相同的名字的話可以使用USING
例如
SELECT FROM LEFT JOIN USING ()

連線多餘兩個表的情況
舉例:
mysql> SELECT  artists.Artist, cds.title, genres.genre 
    -> FROM cds
    -> LEFT JOIN genres 
    -> ON cds.genreID = genres.genreID 
    -> LEFT JOIN artists 
    -> ON cds.artistID = artists.artistID;
或者
mysql> SELECT artists.Artist, cds.title, genres.genre 
    -> FROM cds
    -> LEFT JOIN genres 
    -> ON cds.genreID = genres.genreID 
    -> LEFT JOIN artists 
    -> ON cds.artistID = artists.artistID 
    -> WHERE (genres.genre = 'Pop');
-------------------------------------------- 

另外需要注意的地方

在MySQL中涉及到多表查詢的時候,需要根據查詢的情況,想好使用哪種連線方式效率更高。
1. 交叉連線(笛卡爾積)或者內連線
[INNER | CROSS] JOIN
2. 左外連線LEFT [OUTER] JOIN或者右外連線RIGHT [OUTER] JOIN 

注意指定連線條件WHERE, ON,USING.

--------------------------------------------
看懂MySQL手冊定義的MySQL各種JOIN的用法:
//看懂如下的定義方式
table_references:
    table_reference [, 
table_reference] ...

//不同的JOIN EXPRESSION之間使用','分割
A table reference is also known as a join expression.


table_reference:
    table_factor
  | join_table


//每個JOIN EXPRESSION由資料表table_factor以及JOIN表示式構成join_table 

table_factor:
    
tbl_name [[AS] alias] [index_hint)]
  | ( table_references )
  | { OJ 
table_reference LEFT OUTER JOIN table_reference
        ON conditional_expr }


//資料表table_factor,注意其遞迴定義的table_references


join_table:
    table_reference [INNER | CROSS] JOIN 
table_factor [join_condition]
  | table_reference STRAIGHT_JOIN 
table_factor
  | table_reference STRAIGHT_JOIN table_factor ON condition
  | 
table_reference LEFT [OUTER] JOIN table_reference join_condition
  | 
table_reference NATURAL [LEFT [OUTER]] JOIN table_factor
  | table_reference RIGHT [OUTER] JOIN 
table_reference join_condition
  | table_reference NATURAL [RIGHT [OUTER]] JOIN table_factor


//資料表的連線表示式join_table 

join_condition:
    ON conditional_expr

  | USING (column_list)

//連線表示式的連線條件定義使用ON或者USING 

index_hint:
    USE {INDEX|KEY} [FOR JOIN] (index_list
)
  | IGNORE {INDEX|KEY} [FOR JOIN] (index_list)
  | FORCE {INDEX|KEY} [FOR JOIN] (index_list)


index_list:
    index_name [, index_name] ...

MySQL手冊中提到的JOIN需要注意的地方:

1. 
In MySQL, CROSS JOIN is a syntactic equivalent to INNER JOIN (they can replace each other). In standard SQL, they are not equivalent. INNER JOIN is used with an ON clause, CROSS JOIN is used otherwise.
手冊中提到
標準SQL中CROSS JOIN交叉連線(笛卡爾積)和內連線INNER JOIN不同,但是MySQL中兩者是相同的,即有[CROSS | INNER] JOIN,兩者可以互相替代,而且可以只使用JOIN

2. A table reference can be aliased using tbl_name AS alias_name or tbl_name alias_name:
SELECT t1.name, t2.salary
  FROM employee AS t1 INNER JOIN info AS t2 ON t1.name = t2.name; 
可以對資料表使用別名

3. ,運算子
例如
SELECT * FROM table1,table2 
由於在MySQL中INNER JOIN與CROSS JOIN相同,INNER JOIN和 , 在MySQL也相同,都是產生兩個表的笛卡爾積Cartesian Product
(等於兩個表格的行數乘積)

但是,號的優先順序要低於INNER JOIN, CROSS JOIN, LEFT JOIN

因此
If you mix comma joins with the other join types when there is a join condition, an error of the form. Unknown column 'col_name' in 'on clause' may occur.

4. 什麼時候使用ON,什麼時候使用WHERE
ON應該使用者資料表連線的時候指定連線條件;

WHERE用於使用者限制所選取的列

例如ON a.column=b.column
WHERE a.column='hello'

5. 可以使用LEFT JOIN檢視,兩個連線的表中,不符合連線條件的部分,因為不符合條件的部分LEFT JOIN之後會顯示為NULL 
 If there is no matching row for the right table in the ON or USING part in a LEFT JOIN, a row with all columns set to NULL is used for the right table. You can use this fact to find rows in a table that have no counterpart in another table:


SELECT left_tbl.*
  FROM left_tbl LEFT JOIN right_tbl ON left_tbl.id = right_tbl.id
  WHERE right_tbl.id IS NULL;

This example finds all rows in left_tbl with an id value that is not present in right_tbl (that is, all rows in left_tbl with no corresponding row in right_tbl). This assumes that right_tbl.id is declared NOT NULL. 


6.
當別連線的表指定連線條件的列舉有相同的名稱的時候,不需要
ON a.column=b.column不同的時候才使用ON a.column_a=b.column_b
可以使用USING (column)
當然也可以使用多個USING (c1,c2,c3)

The USING(column_list) clause names a list of columns that must exist in both tables. If tables a and b both contain columns c1, c2, and c3, the following join compares corresponding columns from the two tables:


a LEFT JOIN b USING (c1,c2,c3)

7.
其他的:
#
The NATURAL [LEFT] JOIN of two tables is defined to be semantically equivalent to an INNER JOIN or a LEFT JOIN with a USING clause that names all columns that exist in both tables.

#
RIGHT JOIN works analogously to LEFT JOIN. To keep code portable across databases, it is recommended that you use LEFT JOIN instead of RIGHT JOIN.
#
The { OJ ... LEFT OUTER JOIN ...} syntax shown in the join syntax description exists only for compatibility with ODBC. The curly braces in the syntax should be written literally; they are not metasyntax as used elsewhere in syntax descriptions.

#
STRAIGHT_JOIN is similar to JOIN, except that the left table is always read before the right table. This can be used for those (few) cases for which the join optimizer puts the tables in the wrong order.