1. 程式人生 > >MySQL中join的用法

MySQL中join的用法

近期用phpcms v9做專案,初期沒有問題,後期隨著資料量的增大,phpcms v9後臺出現的欄目更新不動的情況,初期我以為是程式的問題,進行了程式排查,沒有發現任何問題,登入上centos伺服器後free命令發現記憶體也沒有滿。瞬間感覺很蛋疼,不知如何處理,後來登入阿里雲賬號,發現更新欄目時,cpu使用率直接到達100%,xhell遠端登入進入伺服器後用top檢測cpu使用率的情況,發現MySQL佔用的cpu使用率的100%,直接登入進入MySQL資料庫,輸入show full processlist; 可以看到正在執行的語句。看到是一條巢狀的sql語句執行異常緩慢!由於做專案之前沒有考慮到資料量的問題,所以出現這樣的情況,想比較巢狀的sql語句,關聯查詢效能效率會高很多,多表關聯查詢有一個關鍵的詞就是join。

JOIN的含義就如英文單詞“join”一樣,連線兩張表,大致分為內連線,外連線,右連線,左連線,自然連線。這裡描述先甩出一張用爛了的圖,然後插入測試資料。

 View Code

笛卡爾積:CROSS JOIN

要理解各種JOIN首先要理解笛卡爾積。笛卡爾積就是將A表的每一條記錄與B表的每一條記錄強行拼在一起。所以,如果A表有n條記錄,B表有m條記錄,笛卡爾積產生的結果就會產生n*m條記錄。下面的例子,t_blog有10條記錄,t_type有5條記錄,所有他們倆的笛卡爾積有50條記錄。有五種產生笛卡爾積的方式如下。

 View Code

內連線:INNER JOIN

內連線INNER JOIN是最常用的連線操作。從數學的角度講就是求兩個表的交集,從笛卡爾積的角度講就是從笛卡爾積中挑出ON子句條件成立的記錄。有INNER JOIN,WHERE(等值連線),STRAIGHT_JOIN,JOIN(省略INNER)四種寫法。至於哪種好我會在MySQL的JOIN(二):優化

講述。示例如下。

複製程式碼

複製程式碼

    SELECT * FROM t_blog INNER JOIN t_type ON t_blog.typeId=t_type.id;
    SELECT * FROM t_blog,t_type WHERE t_blog.typeId=t_type.id;
    SELECT * FROM t_blog STRAIGHT_JOIN t_type ON t_blog.typeId=t_type.id; --注意STRIGHT_JOIN有個下劃線
    SELECT * FROM t_blog JOIN t_type ON t_blog.typeId=t_type.id;

    +----+-------+--------+----+------+
    | id | title | typeId | id | name |
    +----+-------+--------+----+------+
    |  1 | aaa   |      1 |  1 | C++  |
    |  2 | bbb   |      2 |  2 | C    |
    |  7 | ggg   |      2 |  2 | C    |
    |  3 | ccc   |      3 |  3 | Java |
    |  6 | fff   |      3 |  3 | Java |
    |  4 | ddd   |      4 |  4 | C#   |
    |  5 | eee   |      4 |  4 | C#   |
    +----+-------+--------+----+------+

複製程式碼

複製程式碼

左連線:LEFT JOIN

左連線LEFT JOIN的含義就是求兩個表的交集外加左表剩下的資料。依舊從笛卡爾積的角度講,就是先從笛卡爾積中挑出ON子句條件成立的記錄,然後加上左表中剩餘的記錄(見最後三條)。

複製程式碼

複製程式碼

    SELECT * FROM t_blog LEFT JOIN t_type ON t_blog.typeId=t_type.id;

    +----+-------+--------+------+------+
    | id | title | typeId | id   | name |
    +----+-------+--------+------+------+
    |  1 | aaa   |      1 |    1 | C++  |
    |  2 | bbb   |      2 |    2 | C    |
    |  7 | ggg   |      2 |    2 | C    |
    |  3 | ccc   |      3 |    3 | Java |
    |  6 | fff   |      3 |    3 | Java |
    |  4 | ddd   |      4 |    4 | C#   |
    |  5 | eee   |      4 |    4 | C#   |
    |  8 | hhh   |   NULL | NULL | NULL |
    |  9 | iii   |   NULL | NULL | NULL |
    | 10 | jjj   |   NULL | NULL | NULL |
    +----+-------+--------+------+------+

複製程式碼

複製程式碼

右連線:RIGHT JOIN

同理右連線RIGHT JOIN就是求兩個表的交集外加右表剩下的資料。再次從笛卡爾積的角度描述,右連線就是從笛卡爾積中挑出ON子句條件成立的記錄,然後加上右表中剩餘的記錄(見最後一條)。

複製程式碼

複製程式碼

    SELECT * FROM t_blog RIGHT JOIN t_type ON t_blog.typeId=t_type.id;

    +------+-------+--------+----+------------+
    | id   | title | typeId | id | name       |
    +------+-------+--------+----+------------+
    |    1 | aaa   |      1 |  1 | C++        |
    |    2 | bbb   |      2 |  2 | C          |
    |    3 | ccc   |      3 |  3 | Java       |
    |    4 | ddd   |      4 |  4 | C#         |
    |    5 | eee   |      4 |  4 | C#         |
    |    6 | fff   |      3 |  3 | Java       |
    |    7 | ggg   |      2 |  2 | C          |
    | NULL | NULL  |   NULL |  5 | Javascript |
    +------+-------+--------+----+------------+

複製程式碼

複製程式碼

外連線:OUTER JOIN

外連線就是求兩個集合的並集。從笛卡爾積的角度講就是從笛卡爾積中挑出ON子句條件成立的記錄,然後加上左表中剩餘的記錄,最後加上右表中剩餘的記錄。另外MySQL不支援OUTER JOIN,但是我們可以對左連線和右連線的結果做UNION操作來實現。

複製程式碼

複製程式碼

    SELECT * FROM t_blog LEFT JOIN t_type ON t_blog.typeId=t_type.id
    UNION
    SELECT * FROM t_blog RIGHT JOIN t_type ON t_blog.typeId=t_type.id;

    +------+-------+--------+------+------------+
    | id   | title | typeId | id   | name       |
    +------+-------+--------+------+------------+
    |    1 | aaa   |      1 |    1 | C++        |
    |    2 | bbb   |      2 |    2 | C          |
    |    7 | ggg   |      2 |    2 | C          |
    |    3 | ccc   |      3 |    3 | Java       |
    |    6 | fff   |      3 |    3 | Java       |
    |    4 | ddd   |      4 |    4 | C#         |
    |    5 | eee   |      4 |    4 | C#         |
    |    8 | hhh   |   NULL | NULL | NULL       |
    |    9 | iii   |   NULL | NULL | NULL       |
    |   10 | jjj   |   NULL | NULL | NULL       |
    | NULL | NULL  |   NULL |    5 | Javascript |
    +------+-------+--------+------+------------+

複製程式碼

複製程式碼

USING子句

MySQL中連線SQL語句中,ON子句的語法格式為:table1.column_name = table2.column_name。當模式設計對聯接表的列採用了相同的命名樣式時,就可以使用 USING 語法來簡化 ON 語法,格式為:USING(column_name)。 
所以,USING的功能相當於ON,區別在於USING指定一個屬性名用於連線兩個表,而ON指定一個條件。另外,SELECT *時,USING會去除USING指定的列,而ON不會。例項如下。

複製程式碼

複製程式碼

    SELECT * FROM t_blog INNER JOIN t_type ON t_blog.typeId =t_type.id;
    +----+-------+--------+----+------+
    | id | title | typeId | id | name |
    +----+-------+--------+----+------+
    |  1 | aaa   |      1 |  1 | C++  |
    |  2 | bbb   |      2 |  2 | C    |
    |  7 | ggg   |      2 |  2 | C    |
    |  3 | ccc   |      3 |  3 | Java |
    |  6 | fff   |      3 |  3 | Java |
    |  4 | ddd   |      4 |  4 | C#   |
    |  5 | eee   |      4 |  4 | C#   |
    +----+-------+--------+----+------+


    SELECT * FROM t_blog INNER JOIN t_type USING(typeId);
    ERROR 1054 (42S22): Unknown column 'typeId' in 'from clause'
    SELECT * FROM t_blog INNER JOIN t_type USING(id); -- 應為t_blog的typeId與t_type的id不同名,無法用Using,這裡用id代替下。
    +----+-------+--------+------------+
    | id | title | typeId | name       |
    +----+-------+--------+------------+
    |  1 | aaa   |      1 | C++        |
    |  2 | bbb   |      2 | C          |
    |  3 | ccc   |      3 | Java       |
    |  4 | ddd   |      4 | C#         |
    |  5 | eee   |      4 | Javascript |
    +----+-------+--------+------------+

複製程式碼

複製程式碼

自然連線:NATURE JOIN

自然連線就是USING子句的簡化版,它找出兩個表中相同的列作為連線條件進行連線。有左自然連線右自然連線普通自然連線之分。在t_blog和t_type示例中,兩個表相同的列是id,所以會拿id作為連線條件。 
另外千萬分清下面三條語句的區別 。
自然連線:SELECT * FROM t_blog NATURAL JOIN t_type; 
笛卡爾積:SELECT * FROM t_blog NATURA JOIN t_type; 
笛卡爾積:SELECT * FROM t_blog NATURE JOIN t_type;

 View Code

補充

部落格開頭給出的第一張圖除去講了的內連線、左連線、右連線、外連線,還有一些特殊的韋恩圖,這裡補充一下。

 View Code

寫完這篇部落格發現有點“孔乙己:茴字的四種寫法的感覺”,但還是有收穫的。另外,等三面通知等的好急啊!!