程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> 深刻懂得mysql之left join 應用詳解

深刻懂得mysql之left join 應用詳解

編輯:MySQL綜合教程

深刻懂得mysql之left join 應用詳解。本站提示廣大學習愛好者:(深刻懂得mysql之left join 應用詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是深刻懂得mysql之left join 應用詳解正文


 ON 子句與 WHERE 子句的分歧
    一種更好地輿解帶有 WHERE ... IS NULL 子句的龐雜婚配前提的簡略辦法
    Matching-Conditions 與 Where-conditions 的分歧

關於 “A LEFT JOIN B ON 前提表達式” 的一點提示

ON 前提(“A LEFT JOIN B ON 前提表達式”中的ON)用來決議若何從 B 表中檢索數據行。

假如 B 表中沒有任何一行數據婚配 ON 的前提,將會額定生成一行一切列為 NULL 的數據

在婚配階段 WHERE 子句的前提都不會被應用。僅在婚配階段完成今後,WHERE 子句前提才會被應用。它將從婚配階段發生的數據中檢索過濾。

讓我們看一個 LFET JOIN 示例:

mysql> CREATE TABLE `product` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `amount` int(10) unsigned default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=latin1

mysql> CREATE TABLE `product_details` (
  `id` int(10) unsigned NOT NULL,
  `weight` int(10) unsigned default NULL,
  `exist` int(10) unsigned default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

mysql> INSERT INTO product (id,amount)
       VALUES (1,100),(2,200),(3,300),(4,400);
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> INSERT INTO product_details (id,weight,exist)
       VALUES (2,22,0),(4,44,1),(5,55,0),(6,66,1);
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM product;
+----+--------+
| id | amount |
+----+--------+
|  1 |    100 |
|  2 |    200 |
|  3 |    300 |
|  4 |    400 |
+----+--------+
4 rows in set (0.00 sec)

mysql> SELECT * FROM product_details;
+----+--------+-------+
| id | weight | exist |
+----+--------+-------+
|  2 |     22 |     0 |
|  4 |     44 |     1 |
|  5 |     55 |     0 |
|  6 |     66 |     1 |
+----+--------+-------+
4 rows in set (0.00 sec)

mysql> SELECT * FROM product LEFT JOIN product_details
       ON (product.id = product_details.id);
+----+--------+------+--------+-------+
| id | amount | id   | weight | exist |
+----+--------+------+--------+-------+
|  1 |    100 | NULL |   NULL |  NULL |
|  2 |    200 |    2 |     22 |     0 |
|  3 |    300 | NULL |   NULL |  NULL |
|  4 |    400 |    4 |     44 |     1 |
+----+--------+------+--------+-------+
4 rows in set (0.00 sec)

ON 子句和 WHERE 子句有甚麼分歧?

一個成績:上面兩個查詢的成果集有甚麼分歧麼?

1. SELECT * FROM product LEFT JOIN product_details
         ON (product.id = product_details.id)
         AND   product_details.id=2;
2. SELECT * FROM product LEFT JOIN product_details
         ON (product.id = product_details.id)
         WHERE product_details.id=2;

用例子來懂得最好不外了:

mysql> SELECT * FROM product LEFT JOIN product_details
       ON (product.id = product_details.id)
       AND product_details.id=2;
+----+--------+------+--------+-------+
| id | amount | id   | weight | exist |
+----+--------+------+--------+-------+
|  1 |    100 | NULL |   NULL |  NULL |
|  2 |    200 |    2 |     22 |     0 |
|  3 |    300 | NULL |   NULL |  NULL |
|  4 |    400 | NULL |   NULL |  NULL |
+----+--------+------+--------+-------+
4 rows in set (0.00 sec)

mysql> SELECT * FROM product LEFT JOIN product_details
       ON (product.id = product_details.id)
       WHERE product_details.id=2;
+----+--------+----+--------+-------+
| id | amount | id | weight | exist |
+----+--------+----+--------+-------+
|  2 |    200 |  2 |     22 |     0 |
+----+--------+----+--------+-------+
1 row in set (0.01 sec)

第一條查詢應用 ON 前提決議了從 LEFT JOIN的 product_details表中檢索相符的一切數據行。

第二條查詢做了簡略的LEFT JOIN,然後應用 WHERE 子句從 LEFT JOIN的數據中過濾失落不相符前提的數據行。

再來看一些示例:

mysql>
mysql> SELECT * FROM product LEFT JOIN product_details
       ON product.id = product_details.id
       AND product.amount=100;
+----+--------+------+--------+-------+
| id | amount | id   | weight | exist |
+----+--------+------+--------+-------+
|  1 |    100 | NULL |   NULL |  NULL |
|  2 |    200 | NULL |   NULL |  NULL |
|  3 |    300 | NULL |   NULL |  NULL |
|  4 |    400 | NULL |   NULL |  NULL |
+----+--------+------+--------+-------+
4 rows in set (0.00 sec)

一切來自product表的數據行都被檢索到了,但沒有在product_details表中婚配到記載(product.id = product_details.id AND product.amount=100 前提並沒有婚配就任何數據)

mysql> SELECT * FROM product LEFT JOIN product_details
       ON (product.id = product_details.id)
       AND product.amount=200;
+----+--------+------+--------+-------+
| id | amount | id   | weight | exist |
+----+--------+------+--------+-------+
|  1 |    100 | NULL |   NULL |  NULL |
|  2 |    200 |    2 |     22 |     0 |
|  3 |    300 | NULL |   NULL |  NULL |
|  4 |    400 | NULL |   NULL |  NULL |
+----+--------+------+--------+-------+
4 rows in set (0.01 sec)

異樣,一切來自product表的數據行都被檢索到了,有一條數據婚配到了。

應用 WHERE ... IS NULL 子句的 LEFT JOIN

當你應用 WHERE ... IS NULL 子句時會產生甚麼呢?

如前所述,WHERE 前提查詢產生在 婚配階段以後,這意味著 WHERE ... IS NULL 子句將從婚配階段後的數據中過濾失落不知足婚配前提的數據行。

紙面上看起來很清晰,然則當你在 ON 子句中應用多個前提時就會覺得迷惑了。

我總結了一種簡略的方法來懂得上述情形:

    將 IS NULL 作為否認婚配前提
    應用 !(A and B) == !A OR !B 邏輯斷定

看看上面的示例:

mysql> SELECT a.* FROM product a LEFT JOIN product_details b
       ON a.id=b.id AND b.weight!=44 AND b.exist=0
       WHERE b.id IS NULL;
+----+--------+
| id | amount |
+----+--------+
|  1 |    100 |
|  3 |    300 |
|  4 |    400 |
+----+--------+
3 rows in set (0.00 sec)

讓我們檢討一下 ON 婚配子句:

(a.id=b.id) AND (b.weight!=44) AND (b.exist=0)

我們可以把 IS NULL 子句 看做能否定婚配前提。

這意味著我們將檢索到以下行:

!( exist(b.id that equals to a.id) AND b.weight !=44 AND b.exist=0 )
!exist(b.id that equals to a.id) || !(b.weight !=44) || !(b.exist=0)
!exist(b.id that equals to a.id) || b.weight =44 || b.exist=1

就像在C說話中的邏輯 AND 和 邏輯 OR表達式一樣,其操作數是從左到右求值的。假如第一個參數做夠斷定操作成果,那末第二個參數便不會被盤算求值(短路後果)

看看其余示例:

mysql> SELECT a.* FROM product a LEFT JOIN product_details b
       ON a.id=b.id AND b.weight!=44 AND b.exist=1
       WHERE b.id IS NULL;
+----+--------+
| id | amount |
+----+--------+
|  1 |    100 |
|  2 |    200 |
|  3 |    300 |
|  4 |    400 |
+----+--------+
4 rows in set (0.00 sec)

Matching-Conditions 與 Where-conditions 之戰

假如你吧根本的查詢前提放在 ON 子句中,把剩下的否認前提放在 WHERE 子句中,那末你會取得雷同的成果。

例如,你可以不如許寫:

SELECT a.* FROM product a LEFT JOIN product_details b
ON a.id=b.id AND b.weight!=44 AND b.exist=0
WHERE b.id IS NULL;

你可以如許寫:

SELECT a.* FROM product a LEFT JOIN product_details b
ON a.id=b.id
WHERE b.id is null OR b.weight=44 OR b.exist=1;

mysql> SELECT a.* FROM product a LEFT JOIN product_details b
       ON a.id=b.id
       WHERE b.id is null OR b.weight=44 OR b.exist=1;
+----+--------+
| id | amount |
+----+--------+
|  1 |    100 |
|  3 |    300 |
|  4 |    400 |
+----+--------+
3 rows in set (0.00 sec)

你可以不如許寫:

SELECT a.* FROM product a LEFT JOIN product_details b
ON a.id=b.id AND b.weight!=44 AND b.exist!=0
WHERE b.id IS NULL;

可以如許寫:

SELECT a.* FROM product a LEFT JOIN product_details b
ON a.id=b.id
WHERE b.id is null OR b.weight=44 OR b.exist=0;

mysql> SELECT a.* FROM product a LEFT JOIN product_details b
       ON a.id=b.id
       WHERE b.id is null OR b.weight=44 OR b.exist=0;
+----+--------+
| id | amount |
+----+--------+
|  1 |    100 |
|  2 |    200 |
|  3 |    300 |
|  4 |    400 |
+----+--------+
4 rows in set (0.00 sec)

這些查詢真的後果一樣?

假如你只須要第一個表中的數據的話,這些查詢會前往雷同的成果集。有一種情形就是,假如你從 LEFT JOIN的表中檢索數據時,查詢的成果就分歧了。

如前所屬,WHERE 子句是在婚配階段以後用來過濾的。

例如:

mysql> SELECT * FROM product a LEFT JOIN product_details b
       ON a.id=b.id AND b.weight!=44 AND b.exist=1
       WHERE b.id is null;
+----+--------+------+--------+-------+
| id | amount | id   | weight | exist |
+----+--------+------+--------+-------+
|  1 |    100 | NULL |   NULL |  NULL |
|  2 |    200 | NULL |   NULL |  NULL |
|  3 |    300 | NULL |   NULL |  NULL |
|  4 |    400 | NULL |   NULL |  NULL |
+----+--------+------+--------+-------+
4 rows in set (0.00 sec)

mysql> SELECT * FROM product a LEFT JOIN product_details b
       ON a.id=b.id
       WHERE b.id IS NULL OR b.weight=44 OR b.exist=0;
+----+--------+------+--------+-------+
| id | amount | id   | weight | exist |
+----+--------+------+--------+-------+
|  1 |    100 | NULL |   NULL |  NULL |
|  2 |    200 |    2 |     22 |     0 |
|  3 |    300 | NULL |   NULL |  NULL |
|  4 |    400 |    4 |     44 |     1 |
+----+--------+------+--------+-------+
4 rows in set (0.00 sec)

總附注:

假如你應用 LEFT JOIN 來尋覓在一些表中不存在的記載,你須要做上面的測試:WHERE 部門的 col_name IS NULL(個中 col_name 列被界說為 NOT NULL),MYSQL 在查詢到一條婚配 LEFT JOIN 前提後將停滯搜刮更多行(在一個特定的組合鍵下)。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved