2013-03-11 128 views
0

什麼可能會使這兩個查詢不同?SQL Natural連接和嵌套SELECT查詢

該帖子確實主要是代碼。

SELECT DISTINCT S.name 
FROM 
    student S NATURAL JOIN taking NATURAL JOIN 
    (select * from class where classnum ='121') 
WHERE 
    department='CMPSC' 
    AND semester='Spring 2013'; 



SELECT DISTINCT S.name 
FROM 
    student S NATURAL JOIN taking NATURAL JOIN class 
WHERE 
    department='CMPSC' 
    AND semester='Spring 2013' 
    AND classnum='121'; 

謝謝!

編輯:

至於用於解釋命令請求的響應:我不得不這樣做對ORACLE,所以我不知道這是預期的結果:

這是第一個查詢:

Plan hash value: 3259400360 

------------------------------------------------------ 
| Id | Operation      | Name   | 
------------------------------------------------------ 
| 0 | SELECT STATEMENT    |    | 
| 1 | HASH UNIQUE     |    | 
| 2 | NESTED LOOPS    |    | 
| 3 | NESTED LOOPS    |    | 
| 4 |  TABLE ACCESS FULL   | CLASS  | 
| 5 |  INDEX FULL SCAN   | SYS_C0099014 | 
| 6 | TABLE ACCESS BY INDEX ROWID| STUDENT  | 
| 7 |  INDEX UNIQUE SCAN   | SYS_C0098998 | 
------------------------------------------------------ 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    4 - filter("CLASSNUM"=121 AND "CLASS"."SEMESTER"='Spring 2013' AND 
       "CLASS"."DEPARTMENT"='CMPSC') 

PLAN_TABLE_OUTPUT 
-------------------------------------------------------------------------------- 
    5 - access("TAKING"."SCHEDULENUM"="CLASS"."SCHEDULENUM" AND 
       "TAKING"."SEMESTER"='Spring 2013') 
     filter("TAKING"."SEMESTER"='Spring 2013' AND 
       "TAKING"."SCHEDULENUM"="CLASS"."SCHEDULENUM") 
    7 - access("S"."STUDENTNUM"="TAKING"."STUDENTNUM") 

第二個查詢:

PLAN_TABLE_OUTPUT 
-------------------------------------------------------------------------------- 
Plan hash value: 226170808 

------------------------------------------------------- 
| Id | Operation      | Name   | 
------------------------------------------------------- 
| 0 | SELECT STATEMENT    |    | 
| 1 | HASH UNIQUE     |    | 
| 2 | HASH JOIN     |    | 
| 3 | MERGE JOIN     |    | 
| 4 |  TABLE ACCESS BY INDEX ROWID| STUDENT  | 
| 5 |  INDEX FULL SCAN   | SYS_C0098998 | 
| 6 |  SORT JOIN     |    | 
| 7 |  INDEX FULL SCAN   | SYS_C0099014 | 
| 8 | TABLE ACCESS FULL   | CLASS  | 
------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

PLAN_TABLE_OUTPUT 
-------------------------------------------------------------------------------- 

    2 - access("TAKING"."SEMESTER"="CLASS"."SEMESTER") 
    6 - access("S"."STUDENTNUM"="TAKING"."STUDENTNUM") 
     filter("S"."STUDENTNUM"="TAKING"."STUDENTNUM") 
    7 - access("TAKING"."SEMESTER"='Spring 2013') 
     filter("TAKING"."SEMESTER"='Spring 2013') 
    8 - filter("CLASS"."CLASSNUM"=121 AND "CLASS"."SEMESTER"='Spring 2013' AND 
       "CLASS"."DEPARTMENT"='CMPSC') 
+1

你是說結果不同還是表現?如果結果不同,請張貼示例。 – 2013-03-11 04:07:01

+0

嘗試在兩個查詢上運行'explain'以獲取查詢執行計劃;比較他們看到的差異。也張貼他們在這裏爲他人分析。 [解釋語法](http://dev.mysql.com/doc/refman/5.0/en/explain.html) – Kshitij 2013-03-11 04:15:49

+0

@Kshitij我希望這是你所要求的,我正在運行Oracle。 – ammoun 2013-03-11 04:43:43

回答

0

如果性能是問題,這是貝科用你擊敗索引。當執行子查詢時,服務器可以使用索引來檢索結果;然而,它不能索引子查詢的結果,導致更差的性能。一般來說,嘗試「優化」優化器效果不佳 - 您最終會遇到難以閱讀的查詢,並執行完全相同的操作(優化器會將查詢優化爲與原始操作相同的內容),或者您最終會出現這樣的情況,表現更糟糕。應該使用JOIN子句來定義連接,而不是限制數據。

優化器將相同執行以下查詢:

SELECT * 
FROM foo f 
    JOIN bar b 
    ON f.id = b.id 
     AND b.col = 'baz' 

SELECT * 
FROM foo f 
    JOIN bar b 
    ON f.id = b.id 
WHERE b.col = 'baz' 

SELECT * 
FROM foo f 
    JOIN (
    SELECT * 
    FROM bar b 
    WHERE col = 'baz' 
) AS b 
    ON f.id = b.id 

在MySQL基本上產生非索引存儲器內臨時表。它執行與前面兩個sql服務器中的相同。

+0

這是非常有趣的邁克爾,你可以看看解釋輸出? – ammoun 2013-03-11 04:54:38

+0

它看起來像SQL Server實際上將所有三個查詢優化爲相同的。但是,MySQL不會。查看這些SQL Fiddles並單擊'查看執行計劃':[SQL Fiddle Query#1](http://sqlfiddle.com/#!2/fd343/1),[SQL Fiddle Query#2](http:// sqlfiddle.com/#!2/fd343/3),[SQL Fiddle Query#3](http://sqlfiddle.com/#!2/fd343/2) – 2013-03-11 12:19:29