簡體   English   中英

如何在連接兩個表后僅選擇唯一的行

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM