Sql-Server

EXISTS (SELECT 1 …) vs EXISTS (SELECT * …) 一個還是另一個?

  • August 28, 2018

每當我需要檢查表中是否存在某行時,我傾向於始終編寫如下條件:

SELECT a, b, c
 FROM a_table
WHERE EXISTS
      (SELECT *  -- This is what I normally write
         FROM another_table
        WHERE another_table.b = a_table.b
      )

其他一些人這樣寫:

SELECT a, b, c
 FROM a_table
WHERE EXISTS
      (SELECT 1   --- This nice '1' is what I have seen other people use
         FROM another_table
        WHERE another_table.b = a_table.b
      )

當條件NOT EXISTS不是EXISTS: 在某些情況下,我可能會用 aLEFT JOIN和一個額外的條件(有時稱為antijoin)來編寫它:

SELECT a, b, c
 FROM a_table
      LEFT JOIN another_table ON another_table.b = a_table.b
WHERE another_table.primary_key IS NULL

我盡量避免使用它,因為我認為含義不太清楚,特別是當您primary_key的內容不那麼明顯時,或者當您的主鍵或連接條件是多列時(您很容易忘記其中一列)。但是,有時您維護由其他人編寫的程式碼……它就在那裡。

  1. 有什麼區別(除了風格)來SELECT 1代替SELECT *嗎?

有沒有表現不同的極端情況? 2. 雖然我寫的是(AFAIK)標準SQL:不同的數據庫/舊版本有這樣的區別嗎? 3. 明確寫反加入有什麼好處嗎?

當代計劃者/優化者是否將其與NOT EXISTS條款區別對待?

(NOT) EXISTS (SELECT 1 ...)不,(NOT) EXISTS (SELECT * ...)所有主要 DBMS之間的效率沒有差異。我也經常看到(NOT) EXISTS (SELECT NULL ...)被使用。

在某些情況下,您甚至可以編寫(NOT) EXISTS (SELECT 1/0 ...)並且結果是相同的 - 沒有任何(除以零)錯誤,這證明那裡的表達式甚至沒有被評估。


關於LEFT JOIN / IS NULLantijoin 方法,更正一下:這相當於NOT EXISTS (SELECT ...).

在這種情況下,NOT EXISTSvsLEFT JOIN / IS NULL,你可能會得到不同的執行計劃。例如,在 MySQL 中,主要是在舊版本(5.7 之前)中,計劃非常相似,但並不完全相同。據我所知,其他 DBMS(SQL Server、Oracle、Postgres、DB2)的優化器或多或少能夠重寫這兩種方法並為兩者考慮相同的計劃。儘管如此,仍然沒有這樣的保證,並且在進行優化時,最好檢查來自不同等效重寫的計劃,因為可能存在每個優化器不重寫的情況(例如,複雜查詢,具有許多連接和/或派生表/子查詢中的子查詢,其中來自多個表的條件、連接條件中使用的複合列)或優化器選擇和計劃受到可用索引、設置等的不同影響。

另請注意,USING不能在所有 DBMS 中使用(例如 SQL Server)。比較常見的JOIN ... ON作品無處不在。

並且列需要以表名/別名為前綴,SELECT以避免在我們進行連接時出現錯誤/歧義。

我通常也更喜歡將連接的列放在IS NULL檢查中(儘管 PK 或任何不可為空的列都可以,但當計劃LEFT JOIN使用非聚集索引時,它可能對效率很有用):

SELECT a_table.a, a_table.b, a_table.c
 FROM a_table
      LEFT JOIN another_table 
          ON another_table.b = a_table.b
WHERE another_table.b IS NULL ;

還有第三種反連接方法,NOT IN但是如果內部表的列可以為空,則使用它具有不同的語義(和結果!)。它可以通過排除帶有 的行來使用NULL,使查詢等效於前兩個版本:

SELECT a, b, c
 FROM a_table
WHERE a_table.b NOT IN 
      (SELECT another_table.b
         FROM another_table
        WHERE another_table.b IS NOT NULL
      ) ;

這通常也會在大多數 DBMS 中產生類似的計劃。

引用自:https://dba.stackexchange.com/questions/159413