MYSQL中JOIN的用法

近期用phpcms v9作項目,初期沒有問題,後期隨着數據量的增大,phpcms v9後臺出現的欄目更新不動的狀況,初期我覺得是程序的問題,進行了程序排查,沒有發現任何問題,登陸上centos服務器後free命令發現內存也沒有滿。瞬間感受很蛋疼,不知如何處理,後來登陸阿里雲帳號,發現更新欄目時,cpu使用率直接到達100%,xhell遠程登陸進入服務器後用top檢測cpu使用率的狀況,發現MySQL佔用的cpu使用率的100%,直接登陸進入MySQL數據庫,輸入show full processlist; 能夠看到正在執行的語句。看到是一條嵌套的sql語句執行異常緩慢!因爲作項目以前沒有考慮到數據量的問題,因此出現這樣的狀況,想比較嵌套的sql語句,關聯查詢性能效率會高不少,多表關聯查詢有一個關鍵的詞就是join。php

JOIN的含義就如英文單詞「join」同樣,鏈接兩張表,大體分爲內鏈接,外鏈接,右鏈接,左鏈接,天然鏈接。這裏描述先甩出一張用爛了的圖,而後插入測試數據。html

 

  View Code

笛卡爾積:CROSS JOIN

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

  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子句條件成立的記錄,而後加上左表中剩餘的記錄(見最後三條)。centos

複製代碼
複製代碼
    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 | +----+-------+--------+------------+
複製代碼
複製代碼

文章源自貝利-園子

相關文章
相關標籤/搜索