深入淺出:MySQL的左串連、右串連、等值串連

來源:互聯網
上載者:User

author:skate
time:2012/02/18

 

深入淺出:MySQL的左串連、右串連、等值串連

 

三種串連的文法

為便於更多的技友快速讀懂、理解,我們只討論2張表對象進行串連操作的情況,大於2張表對象進行的串連操作原理也是一樣的。

 

1.左串連(LEFT JOIN )

SELECT M.columnname……,N.* columnname…..

FROM left_table M LEFT JOIN right_table N ON M.columnname_join=N.columnname_join AND N.columnname=XXX

WHERE M.columnname=XXX…..

 

2.右串連(RIGHT JOIN)
SELECT M.columnname……,N.* columnname…..

FROM left_table M RIGHT JOIN right_table N ON M. columnname_join=N. columnname_join AND M. columnname=XXX

WHERE N.columnname=XXX…..

 

3.等值串連

SELECT M.columnname……,N.* columnname…..

FROM left_table M [INNER] JOIN right_table N ON M. columnname_join=N. columnname_join

WHERE M.columnname=XXX….. AND N.columnname=XXX….

或者

SELECT M.columnname……,N.* columnname…..

FROM left_table M  , right_table N

WHERE M. columnname_join=N. columnname_join AND
M.columnname=XXX….. AND N.columnname=XXX….

 

說明:

 

A.左串連(LEFT JOIN )

ON字句串連條件,用於把2表中等值的記錄串連在一起,但是不影響記錄集的數量。若是表left_table中的某記錄,無法在表right_table找到對應的記錄,則此記錄依然顯示在記錄集鐘,只是表 right_table需要在查詢顯示的列的值用NULL替代;

 

ON字句串連條件中表right_table.columnname=XXX用於控制right_table表是否有符合要求的列值還是用NULL替換的方式顯示在查詢列中,不影響記錄集的數量;

 

WHERE字句控制記錄是否符合查詢要求,不符合則過濾掉;

 

簡單點說,就是 “left_table.columnname_join=right_table.columnname_join”用於統計兩個表的等值串連的記錄集,on子句
串連條件就是限制right_table的記錄集大小,where子句的條件是限制最終結果集的大小。最終結果集的大小是顯示“left_table“表的所有記錄,和“left_table“匹配的”right_table“的記錄顯示”right_table“列值,不匹配的話,顯示對應的”right_table“顯示為null(最終結果集的大小是left_table刨除where條件的記錄數)

B.右串連(RIGHT JOIN)

ON子句串連條件,用於把2表中等值的記錄串連在一起,若是表right_table中的某記錄,無法在表left_table找到對應的記錄,則表 left_table需要在查詢顯示的列的值用NULL替代;

 

ON子句串連條件中表left_table.columnname=XXX用於控制left_table表是否有符合要求的列值,還是用NULL替換的方式顯示在查詢列表中;

 

WHERE字句控制記錄是否符合查詢要求,不符合則過濾掉;

 

簡單點說,就是 “left_table.columnname_join=right_table.columnname_join”用於統計兩個表的等值串連的記錄集,on子句
串連條件就是限制left_table的記錄集大小,where子句的條件是限制最終結果集的大小。最終結果集的大小是顯示“right_table”表的所有記錄,和“right_table“匹配的”left_table“的記錄顯示”left_table“列值,不匹配的話,顯示對應的”left_table“顯示為null(最終結果集的大小是left_table刨除where條件的記錄數)

C. 等值串連

ON子句串連條件,不再與左串連或右串連的功效一樣,除了作為2表記錄匹配的條件外,還會起到過濾記錄的作用,若left_table中記錄無法在right_table中找到對應的記錄,則會被過濾掉;

 

 WHERE字句,不管是涉及表left_table、表right_table上的限制條件,還是涉及2表串連的條件,都會對記錄集起到過濾作用,把不符合要求的記錄刷選掉;

 
測試資料:

 

建立表
mysql> CREATE TABLE left_table(ID INT UNSIGNED NOT NULL AUTO_INCREMENT,
    -> Username VARCHAR(40) NOT NULL,
    -> Birthday DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
    -> CityID     SMALLINT NOT NULL DEFAULT 0,
    -> CreatDate  TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
    -> AlterDate  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    -> PRIMARY KEY(ID),
    -> KEY idx_username(Username)
    -> )ENGINE=InnoDB CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
Query OK, 0 rows affected (0.11 sec)

 

mysql>
mysql> CREATE TABLE right_table(UID INT UNSIGNED NOT NULL ,
    -> CollectNum MEDIUMINT NOT NULL DEFAULT 0,
    -> BuyNum     MEDIUMINT NOT NULL DEFAULT 0,
    -> SearchNum  MEDIUMINT NOT NULL DEFAULT 0,
    -> CreatDate  TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
    -> AlterDate  TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    -> PRIMARY KEY(UID)
    -> )ENGINE=InnoDB CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
Query OK, 0 rows affected (0.00 sec)

 

插入測試資料

執行如下sql十次
 INSERT INTO left_table(Username,Birthday,CityID,CreatDate,AlterDate)
 VALUES(CONCAT(SUBSTRING(RAND(),3,8),'@qq.com'),DATE_ADD(NOW(),INTERVAL -SUBSTRING(RAND(),3,2) YEAR),SUBSTRING(RAND(),3,2),DATE_ADD(NOW(),INTERVAL -SUBSTRING(RAND(),3,3) DAY),DATE_ADD(NOW(),INTERVAL -SUBSTRING(RAND(),3,2) DAY));

執行一次如下sql
 INSERT INTO right_table
 SELECT ID,SUBSTRING(RAND(),3,4) AS CollectNum,SUBSTRING(RAND(),3,2) AS BuyNum,SUBSTRING(RAND(),3,3) AS       SearchNum,CreatDate,AlterDate FROM left_table WHERE ID%5=1;

查看基礎資料:

mysql> select * from right_table;
+-----+------------+--------+-----------+---------------------+---------------------+
| UID | CollectNum | BuyNum | SearchNum | CreatDate           | AlterDate           |
+-----+------------+--------+-----------+---------------------+---------------------+
|   1 |       2545 |     78 |       171 | 2010-01-13 17:42:37 | 2011-12-16 17:42:37 |
|   6 |       4951 |     96 |       325 | 2009-11-28 17:42:55 | 2011-12-10 17:42:55 |
+-----+------------+--------+-----------+---------------------+---------------------+
2 rows in set (0.00 sec)

 

mysql> select * from left_table;
+----+-----------------+---------------------+--------+---------------------+---------------------+
| ID | Username        | Birthday            | CityID | CreatDate           | AlterDate           |
+----+-----------------+---------------------+--------+---------------------+---------------------+
|  1 | 27311524@qq.com | 1995-02-20 17:42:37 |      5 | 2010-01-13 17:42:37 | 2011-12-16 17:42:37 |
|  2 | 01644610@qq.com | 2004-02-20 17:42:49 |     39 | 2010-03-02 17:42:49 | 2012-01-10 17:42:49 |
|  3 | 89103050@qq.com | 1990-02-20 17:42:52 |     44 | 2010-08-28 17:42:52 | 2012-01-14 17:42:52 |
|  4 | 27363743@qq.com | 1989-02-20 17:42:53 |     32 | 2009-07-09 17:42:53 | 2011-12-03 17:42:53 |
|  5 | 09483603@qq.com | 2003-02-20 17:42:54 |     19 | 2010-03-25 17:42:54 | 2011-11-23 17:42:54 |
|  6 | 38929060@qq.com | 1987-02-20 17:42:55 |     11 | 2009-11-28 17:42:55 | 2011-12-10 17:42:55 |
|  7 | 15852433@qq.com | 1949-02-20 17:42:56 |     68 | 2010-09-17 17:42:56 | 2011-12-27 17:42:56 |
|  8 | 22581017@qq.com | 1967-02-20 17:42:57 |     59 | 2010-06-18 17:42:57 | 2012-01-24 17:42:57 |
|  9 | 54863339@qq.com | 1921-02-20 17:42:59 |     91 | 2009-11-23 17:42:59 | 2012-01-15 17:42:59 |
| 10 | 36242195@qq.com | 1940-02-20 17:43:00 |     51 | 2011-01-09 17:43:00 | 2012-01-02 17:43:00 |
+----+-----------------+---------------------+--------+---------------------+---------------------+
10 rows in set (0.00 sec)

 

mysql> select m.id,m.username from left_table m where m.id<=6;
+----+-----------------+
| id | username        |
+----+-----------------+
|  1 | 27311524@qq.com |
|  2 | 01644610@qq.com |
|  3 | 89103050@qq.com |
|  4 | 27363743@qq.com |
|  5 | 09483603@qq.com |
|  6 | 38929060@qq.com |
+----+-----------------+
6 rows in set (0.02 sec)

 

左串連(left join)

 

編號:sql_1
mysql> select m.id,m.username,n.CollectNum,n.BuyNum from left_table m left join right_table n on m.id=n.uid where m.id <=6;
+----+-----------------+------------+--------+
| id | username        | CollectNum | BuyNum |
+----+-----------------+------------+--------+
|  1 | 27311524@qq.com |       2545 |     78 |
|  2 | 01644610@qq.com |       NULL |   NULL |
|  3 | 89103050@qq.com |       NULL |   NULL |
|  4 | 27363743@qq.com |       NULL |   NULL |
|  5 | 09483603@qq.com |       NULL |   NULL |
|  6 | 38929060@qq.com |       4951 |     96 |
+----+-----------------+------------+--------+
6 rows in set (0.02 sec)

 

編號:sql_2
mysql> select m.id,m.username,n.CollectNum,n.BuyNum from left_table m left join right_table n on m.id=n.uid and  n.SearchNum>300 where m.id <=6;
+----+-----------------+------------+--------+
| id | username        | CollectNum | BuyNum |
+----+-----------------+------------+--------+
|  1 | 27311524@qq.com |       NULL |   NULL |
|  2 | 01644610@qq.com |       NULL |   NULL |
|  3 | 89103050@qq.com |       NULL |   NULL |
|  4 | 27363743@qq.com |       NULL |   NULL |
|  5 | 09483603@qq.com |       NULL |   NULL |
|  6 | 38929060@qq.com |       4951 |     96 |
+----+-----------------+------------+--------+
6 rows in set (0.00 sec)

 

sql_1和sql_2對比
1.兩個結果集的記錄數是一樣的,left_table顯示的列值是一樣的
2.兩個結果集中right_table相應列值是不一樣的

 

為什麼會不一樣呢?
兩個記錄集的記錄數是一樣的,那是因為兩個sql的where條件是一樣,即最終的結果集的數量就會一樣,right_table相應的列值不一樣那是因為在on的條件中sql_2過濾掉了right_table的合格記錄。

右串連也就類似了,下面說下等值串連。

 

帶join的等值串連
mysql> select m.id,m.username,n.CollectNum,n.BuyNum
    -> from left_table m inner join right_table n on m.id=n.uid
    -> where m.id<=6;
+----+-----------------+------------+--------+
| id | username        | CollectNum | BuyNum |
+----+-----------------+------------+--------+
|  1 | 27311524@qq.com |       2545 |     78 |
|  6 | 38929060@qq.com |       4951 |     96 |
+----+-----------------+------------+--------+
2 rows in set (0.00 sec)

mysql> select m.id,m.username,n.CollectNum,n.BuyNum from left_table m inner join right_table n on m.id=n.uid and n.SearchNum >300 where m.id<=6;
+----+-----------------+------------+--------+
| id | username        | CollectNum | BuyNum |
+----+-----------------+------------+--------+
|  6 | 38929060@qq.com |       4951 |     96 |
+----+-----------------+------------+--------+
1 row in set (0.01 sec)

 

從上面的可以看到,這裡的on有了過濾最終結果集的大小的作用了

 

不帶join的等值串連(這種方式我用著比較舒服,因為一直用oracle的)
mysql> select m.id,m.username,n.CollectNum,n.BuyNum
    -> from left_table m,right_table n
    -> where m.id=n.uid and m.id<=6;
+----+-----------------+------------+--------+
| id | username        | CollectNum | BuyNum |
+----+-----------------+------------+--------+
|  1 | 27311524@qq.com |       2545 |     78 |
|  6 | 38929060@qq.com |       4951 |     96 |
+----+-----------------+------------+--------+
2 rows in set (0.00 sec)

mysql>

 

常見錯誤用法的左串連

 

1.錯把限制表right_table的條件,從ON子句中放到WHERE字句中,這樣就會影響最終記錄集大小

mysql> select m.id,m.username,n.CollectNum,n.BuyNum from left_table m left join right_table n on m.id=n.uid and  n.SearchNum>300 where m.id <=6;
+----+-----------------+------------+--------+
| id | username        | CollectNum | BuyNum |
+----+-----------------+------------+--------+
|  1 | 27311524@qq.com |       NULL |   NULL |
|  2 | 01644610@qq.com |       NULL |   NULL |
|  3 | 89103050@qq.com |       NULL |   NULL |
|  4 | 27363743@qq.com |       NULL |   NULL |
|  5 | 09483603@qq.com |       NULL |   NULL |
|  6 | 38929060@qq.com |       4951 |     96 |
+----+-----------------+------------+--------+
6 rows in set (0.00 sec)

 

select m.id,m.username,n.CollectNum,n.BuyNum from left_table m ,right_table n where m.id=n.uid and  m.id <=6 and n.SearchNum > 300;
+----+-----------------+------------+--------+
| id | username        | CollectNum | BuyNum |
+----+-----------------+------------+--------+
|  6 | 38929060@qq.com |       4951 |     96 |
+----+-----------------+------------+--------+
1 row in set (0.00 sec)

 

2.錯把限制表left_table或稱影響最終記錄集的條件,從WHERE子句中放到ON字句中,這樣就相當於增大的最終結果集記錄數

select m.id,m.username,n.CollectNum,n.BuyNum from left_table m ,right_table n where m.id=n.uid and  m.id <=6 and n.SearchNum > 300;
+----+-----------------+------------+--------+
| id | username        | CollectNum | BuyNum |
+----+-----------------+------------+--------+
|  6 | 38929060@qq.com |       4951 |     96 |
+----+-----------------+------------+--------+
1 row in set (0.00 sec)

mysql> select m.id,m.username,n.CollectNum,n.BuyNum from left_table m left join right_table n on m.id=n.uid and  n.SearchNum>300 where m.id <=6;
+----+-----------------+------------+--------+
| id | username        | CollectNum | BuyNum |
+----+-----------------+------------+--------+
|  1 | 27311524@qq.com |       NULL |   NULL |
|  2 | 01644610@qq.com |       NULL |   NULL |
|  3 | 89103050@qq.com |       NULL |   NULL |
|  4 | 27363743@qq.com |       NULL |   NULL |
|  5 | 09483603@qq.com |       NULL |   NULL |
|  6 | 38929060@qq.com |       4951 |     96 |
+----+-----------------+------------+--------+
6 rows in set (0.00 sec)

 

 

 

 

 

----------end----------
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.