[英]How to select only the unique rows after joining two table
我有兩張桌子:
table 'A'
| id | name |
| 1 | Larry |
| 2 | Maria |
| 3 | Ponyo |
| 4 | Panda |
table 'B'
| m_id | items |
| 1 | 7 |
| 2 | 9 |
我只想顯示表'A'中不在表'B'上的記錄。 那就是
| 3 | Ponyo |
| 4 | Panda |
只要。
反連接模式通常是最有效的方法,盡管有幾種方法可以獲得相同的結果。
SELECT a.id
, a.name
FROM table_a a
LEFT
JOIN table_b b
ON b.id = a.id
WHERE b.id IS NULL
讓我們解開一下。
LEFT [OUTER] JOIN
操作從a獲取所有行,以及b中的匹配行。 “技巧”是過濾掉所有匹配的行; 為此,我們在WHERE子句中使用謂詞,該謂詞檢查b中的NULL值,如果找到匹配,我們知道該值不為NULL。
在這種情況下,如果我們找到匹配,我們知道b.id不為null,因為如果b.id為NULL,則b.id = a.id
不會返回TRUE。
反連接不會從a創建任何“重復”行(就像常規連接一樣)。 如果您需要消除a中已存在的“重復”,添加GROUP BY子句或在選擇列表之前添加DISTINCT關鍵字是要走的路。
還有其他方法,例如使用帶有相關子查詢的NOT EXISTS
謂詞,或帶子查詢的NOT IN
,但這些表單通常效率不高。
跟進
查詢的實際性能取決於幾個因素; 擁有合適的指數可能是最大的因素。 謂詞中涉及的列的可為空性在執行計划中起作用,基數,值的分布等,MySQL版本和服務器的配置(例如,innodb池大小)也是如此。
作為測試用例:
SHOW VARIABLES LIKE 'version'
-- Variable_name Value
-- ------------- -----------------------------
-- version 5.5.35-0ubuntu0.12.04.2-log
CREATE TABLE `table_a` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`name_` VARCHAR(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB;
CREATE TABLE `table_b` (
`a_id` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`item` INT(10) UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (`a_id`,`item`)
) ENGINE=INNODB;
-- table_a 1,000,000 rows, id values 1 through 1000000
-- table_b 990,000 rows, a_id values 1 through 1000000 (less a_id MOD 100 = 0)
左加入,其中
-- EXPLAIN
SELECT /*! SQL_NO_CACHE */ a.id
, a.name_
FROM table_a a
LEFT
JOIN table_b b
ON b.a_id = a.id
WHERE b.a_id IS NULL
未在
-- EXPLAIN
SELECT /*! SQL_NO_CACHE */ a.id
, a.name_
FROM table_a a
WHERE a.id NOT IN (SELECT b.a_id FROM table_b b)
不存在
-- EXPLAIN
SELECT /*! SQL_NO_CACHE */ a.id
, a.name_
FROM table_a a
WHERE NOT EXISTS
(SELECT 1
FROM table_b b
WHERE b.a_id = a.id)
效果結果(以秒為單位):
run 2 run 3 run 4 run 5 avg
----- ----- ----- ----- -----
left-join-where 0.227 0.227 0.227 0.227 0.227
not-in 0.233 0.233 0.234 0.233 0.233
not-exists 1.031 1.029 1.032 1.031 1.031
三個查詢的EXPLAIN輸出:
left-join-where
id select_type table type possible_ key key_len ref rows Extra
-- ----------- ----- -------------- --------- ------- ------- ------ ------- ------------------------------------
1 SIMPLE a ALL 1000392
1 SIMPLE b ref PRIMARY PRIMARY 4 a.id 1 Using where; Using index; Not exists
not-in
id select_type table type possible_ key key_len ref rows Extra
-- ------------------ ----- -------------- --------- ------- ------- ------ ------- ------------------------------------
1 PRIMARY a ALL 1000392 Using where
2 DEPENDENT SUBQUERY b index_subquery PRIMARY PRIMARY 4 func 1 Using index
not-exists
id select_type table type possible_ key key_len ref rows Extra
-- ------------------ ----- ------ --------- ------- ------- ------ ------- ------------------------------------
1 PRIMARY a ALL 1000392 Using where
2 DEPENDENT SUBQUERY b ref PRIMARY PRIMARY 4 a.id 1 Using index
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.