2010-04-18 245 views
0

哪個更好,有什麼區別?SQL Select查詢

SELECT * FROM TABLE_A A WHERE A.ID IN (SELECT B.ID FROM TABLE_B B) 

SELECT * FROM TABLE_A A, TABLE_B B WHERE A.ID = B.ID 
+0

第二個查詢會起作用嗎? – 2010-04-18 00:51:24

+1

@Mahesh Velaga:是的,從a,b'開始'是交叉連接b'的舊樣式。對於'a'中的每一行,選擇'b'中的所有行。所以'從a,b where a.id = b.id'等同於'從a.id = b.id'的內部連接b'# – Andomar 2010-04-18 01:02:20

+0

@Andomar:謝謝!直到這個較舊的版本兼容哪一點? – 2010-04-18 01:11:58

回答

9

「最佳」 的方式是使用標準的ANSI JOIN語法:

SELECT (columns) 
FROM TABLE_A a 
INNER JOIN TABLE_B b 
    ON b.ID = a.ID 

第一WHERE IN版本將經常結果在相同的執行計劃,但在某些平臺上它可能會變慢 - 它並不總是一致的。當您開始添加更多表或創建更復雜的連接條件時,IN查詢(相當於EXISTS)在編寫和維護時也變得越來越麻煩 - 它不如實際的JOIN那樣靈活。

第二,逗號分隔的語法不如JOIN一貫支持。它在大多數SQL DBMS上都能正常工作,但它不是「首選」版本,因爲如果你忽略了WHERE子句,那麼你最終會得到一個交叉產品。而如果你忘記寫在JOIN的條件下,你最終會出現語法錯誤。由於此安全網,傾向於優先選擇JOIN

+0

+1用於指定列而不是'*'(更好的性能),我希望我可以給你另外一個+1明確指定JOIN ... – CJM 2010-04-18 01:07:35

+0

+1,但在單獨的答案中查看我的意見。 – 2010-04-18 01:38:23

+0

這是一個很好的答案,但是以逗號分隔的語法(這是標準SQL的核心部分和此類功能可能永遠不會從SQL標準中刪除)的說法並不被廣泛支持,這只是不真實的。我甚至會說它是CROSS JOIN語法更廣泛的支持。只需編輯答案。 也考慮到這個問題,強調查詢不一定會返回相同的結果(如http://stackoverflow.com/questions/2660666/sql-select-queries/2661058#2661058) – Unreason 2010-04-19 08:25:43

1

區別在於第一個子查詢可能在某些數據庫中速度較慢。第二個是連接,在同一個查詢中組合兩個表。

通常,如果數據庫不會對其進行優化,則第二種方法會更快,因爲使用子查詢時數據庫必須將子查詢的結果保留在內存中。

3

我upvoted @ Aaronaught的答案,但我有一些意見:

  • 兩個逗號式連接語法和句法JOIN是ANSI。第一個是SQL-89,第二個是SQL-92。 SQL-89語法仍然是標準的一部分,以支持向後兼容性。

  • 你能給出一個支持SQL-92語法但不支持SQL-89的RDBMS的例子嗎?我不認爲有任何,所以「不一致支持」可能不準確。

  • 您還可以使用JOIN語法省略連接條件,並創建笛卡爾積。例如:SELECT ... FROM A JOIN B是有效的(更正:僅在一些鬆散地實現標準語法的品牌(例如MySQL)中才是如此)。

    但是無論如何,我同意當你使用SQL-92語法時,這很容易被發現。如果使用SQL-89語法,則最終可能會生成一條長WHERE子句,並且很容易錯過其中一個加入條件。

+0

'SELECT ... FROM A JOIN B'無效。 JOIN,沒有限定默認爲內部聯接,並且需要ON子句。要得到一個笛卡爾積,你必須說:'SELECT ... FROM CROSS JOIN B'(可能有一些平臺允許'JOIN'沒有ON,但不是標準的。) – 2010-04-18 03:36:50

+0

@Shannon:是的,再右吧。 'JOIN'必須有'ON'或'USING'子句 - *除非你使用'NATURAL'或'UNION'加入修飾符。 – 2010-04-18 04:04:35

+0

Bill:我似乎記得回到SQL Server 2000中,如果您嘗試使用SQL-89語法外連接視圖,將會出現錯誤(「在包含外連接運算符的查詢中無法指定連接的表」)。這是一個奇怪的和神祕的錯誤,通過切換到SQL-92連接來解決。儘管SQL-89仍然是一個標準,但我們都知道一些標準傾向於跨平臺實現。 :)無論如何好點。 – Aaronaught 2010-04-18 07:37:57

1

這兩個查詢返回不同的結果。您只能從第一個TABLE_A中選擇列。

1

有查詢X之間至少三個不同之處:

SELECT * FROM TABLE_A A WHERE A.ID IN (SELECT B.ID FROM TABLE_B B) 

和Y:

SELECT * FROM TABLE_A A, TABLE_B B WHERE A.ID = B.ID 

1)正如Michas說,該組列的將是不同的,其中,查詢ÿ將返回表A & B中的列,但查詢X只返回表A中的列。如果明確指定了您想返回的列,則查詢X只能包含來自表A的列,但查詢Y將包括來自表A的列le B.

2)行數可能不同。如果表B具有比ID匹配從表A中的ID越多,那麼更多的行將與查詢y爲返回比X.

create table TABLE_A (ID int, st VARCHAR(10)) 
create table TABLE_B (ID int, st VARCHAR(10)) 

insert into TABLE_A values (1, 'A-a') 

insert into TABLE_B values (1, 'B-a') 
insert into TABLE_B values (1, 'B-b') 

SELECT * FROM TABLE_A A WHERE A.ID IN (SELECT B.ID FROM TABLE_B B) 

ID   st 
----------- ---------- 
1   A-a 
(1 row(s) affected) 

SELECT * FROM TABLE_A A, TABLE_B B WHERE A.ID = B.ID 

ID   st   ID   st 
----------- ---------- ----------- ---------- 
1   A-a  1   B-a 
1   A-a  1   B-b 
(2 row(s) affected) 

3)執行計劃可能會有所不同,因爲查詢詢問數據庫爲不同的結果。 Inner joins用於運行速度超過inexists,並且在某些情況下仍可能運行得更快。 但由於結果可能不同,因此您需要確保數據支持從inexistsjoin的轉換。

+0

+1,但重新3)取決於a.id和b.id之間的關係,你可能是對的,也可能不是;在一對一或一對一的情況下或在多對一或一對多關係的情況下,查詢將最有可能產生相同的計劃(查詢要求相同的結果)以防一對一 - 多或多對它不會。這取決於。 – Unreason 2010-04-19 08:20:50