萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

SQL IN 與 NOT IN 運算子完整指南:單表、多表與子查詢實戰

基本語法

-- IN:匹配列表中任一值
SELECT column_name(s)
FROM table_name
WHERE column_name IN (value1, value2, ...);

-- NOT IN:排除列表中所有值
SELECT column_name(s)
FROM table_name
WHERE column_name NOT IN (value1, value2, ...);

單表範例:依類別篩選商品

建立 Topic 表並插入 16 筆測試資料(含 Category 欄位)。

-- 查詢 Category 為 'Blues' 或 'Jazz' 的商品
SELECT Name, Category, InStock
FROM Topic
WHERE Category IN ('Blues', 'Jazz')
ORDER BY Name;

-- 結果
+---------+----------+---------+
| Name    | Category | InStock |
+---------+----------+---------+
| C Sharp | Jazz     |      17 |
| Php     | Jazz     |      32 |
| Python  | Blues    |       2 |
+---------+----------+---------+

進階:NOT IN 搭配子查詢進行多表關聯篩選

場景:找出「沒有被姓 'MySQL' 的作者撰寫過的書」對應的版權年份。

建立關聯表

CREATE TABLE Books (
    BookID SMALLINT PRIMARY KEY,
    BookTitle VARCHAR(60),
    Copyright YEAR
) ENGINE=InnoDB;

CREATE TABLE Authors (
    AuthID SMALLINT PRIMARY KEY,
    AuthFN VARCHAR(20), AuthMN VARCHAR(20), AuthLN VARCHAR(20)
) ENGINE=InnoDB;

CREATE TABLE AuthorBook (
    AuthID SMALLINT, BookID SMALLINT,
    PRIMARY KEY (AuthID, BookID),
    FOREIGN KEY (AuthID) REFERENCES Authors(AuthID),
    FOREIGN KEY (BookID) REFERENCES Books(BookID)
) ENGINE=InnoDB;

查詢語句

SELECT BookTitle, Copyright
FROM Books
WHERE Copyright NOT IN (
    SELECT b.Copyright
    FROM Books AS b
    JOIN AuthorBook AS ab ON b.BookID = ab.BookID
    JOIN Authors AS a ON ab.AuthID = a.AuthID
    WHERE a.AuthLN = 'MySQL'
)
ORDER BY BookTitle;

結果說明

子查詢先找出姓 'MySQL' 作者關聯的所有版權年份,外層查詢排除這些年份。最終返回 8 筆資料,包含 Java、JavaScript、MySQL、Oracle 等書籍。

效能與注意事項

  • IN 列表過長(超過數百個值)會降低解析效能,建議改用臨時表或 JOIN。
  • NOT IN + 子查詢含 NULL 會導致結果為空集。若子查詢可能返回 NULL,請改用 NOT EXISTS 或加上 IS NOT NULL 條件。
  • MySQL 8.0+ 可將 IN (subquery) 自動優化為 SEMI JOIN,效能大幅提升。
  • 配合索引:被查詢欄位若有索引,IN 可走 range 掃描,速度極快。

最佳實踐建議

  1. 優先使用 IN 替代多個 OR,可讀性與效能皆優。
  2. 子查詢去重:IN (SELECT DISTINCT ...) 避免重複值干擾優化器。
  3. 大量值匹配時,考慮 INSERT ... VALUES (...) ... 寫入臨時表再 JOIN。
copyright © 萬盛學電腦網 all rights reserved