Oracle(二)SELECT語句執行順序


轉載自:小強齋太-Study Notes,原文鏈接 從join on和where執行順序認識T-SQL查詢處理執行順序

 

目錄

一、樣例

二、SELECT語句的處理過程

1. FROM階段

2. WHERE階段

3. GROUP BY階段

4. HAVING階段

5. SELECT階段

6. ORDER BY階段

三、樣例解釋

 

數據庫SQL(Structure Query Language)包含3種類型的語言:DML(Data Manipulation Language)、DDL(Data Definition Language)和DCL(Data Control Language),其中使用最頻繁的當屬DML,DML包括4條具體的命令,它們是SELECT、UPDATE、INSERT、DELETE,就象它的名字一樣,這4條命令是用來對數據庫里的數據進行操作的語言。這4條命令中,使用最頻繁的是SELECT命令,所有查詢的操作都是通過它來獲取數據庫中的數據。但你是否有思考過,數據庫執行SELECT命令的順序是否與我們寫出的SELECT命令的順序一致?接下來,我們就來分析一下Oracle數據庫執行SELECT命令的順序。

先通過一個例子來看JOIN ON和WHERE執行結果的不同。

一、樣例

CREATE TABLE "SCOTT"."A" (

"PERSON_ID" NUMBER(5) NULL ,

"PERSON_NAME" VARCHAR2(255 BYTE) NULL 

)

;

-- ----------------------------

-- Records of A

-- ----------------------------

INSERT INTO "SCOTT"."A" VALUES ('1', '張三');

INSERT INTO "SCOTT"."A" VALUES ('2', '李四');

INSERT INTO "SCOTT"."A" VALUES ('3', '王五');

INSERT INTO "SCOTT"."A" VALUES ('4', '趙六');

INSERT INTO "SCOTT"."A" VALUES ('5', '周七');

CREATE TABLE "SCOTT"."B" (

"PERSON_ID" NUMBER(5) NULL ,

"LOVE_FRUIT" VARCHAR2(255 BYTE) NULL 

);

-- ----------------------------

-- Records of B

-- ----------------------------

INSERT INTO "SCOTT"."B" VALUES ('1', '香蕉');

INSERT INTO "SCOTT"."B" VALUES ('2', '蘋果');

INSERT INTO "SCOTT"."B" VALUES ('3', '橘子');

INSERT INTO "SCOTT"."B" VALUES ('4', '');

INSERT INTO "SCOTT"."B" VALUES ('8', '');

查詢語句1

SELECT * FROM A LEFT JOIN ORACLE.B ON A.PERSON_ID = B.PERSON_ID AND A.PERSON_ID = 1;

查詢語句2

SELECT * FROM A LEFT JOIN ORACLE.B ON A.PERSON_ID = B.PERSON_ID WHERE A.PERSON_ID = 1;

為什么結果不同呢?可以從查詢邏輯處理的過程解釋。

二、SELECT語句的處理過程

我們知道,SQL 查詢的大致語法結構如下:

(5)SELECT DISTINCT TOP(<top_specification>) <select_list>                     

(1)FROM <left_table> <join_type> JOIN <right_table> ON <on_predicate>

(2)WHERE <where_predicate>

(3)GROUP BY <group_by_specification>

(4)HAVING <having_predicate>

(6)ORDER BY <order_by_list>

SELECT語法的處理順序:

The following steps show the processing order for a SELECT statement.

  1. FROM
  2. ON
  3. JOIN
  4. WHERE
  5. GROUP BY
  6. WITH CUBE or WITH ROLLUP
  7. HAVING
  8. SELECT
  9. DISTINCT
  10. ORDER BY
  11. TOP

這些步驟執行時,每個步驟都會產生一個虛擬表,該虛擬表被用作下一個步驟的輸入。這些虛擬表對調用者(客戶端應用程序或者外部查詢)不可用。只是最后一步生成的表才會返回給調用者。如果沒有在查詢中指定某一子句,將跳過相應的步驟。

SELECT各個階段分別干了什么:

1. FROM階段

 FROM階段標識出查詢的來源表,並處理表運算符。在涉及到聯接運算的查詢中(各種JOIN),主要有以下幾個步驟:

  • 求笛卡爾積。不論是什么類型的聯接運算,首先都是執行交叉連接(CROSS JOIN),求笛卡兒積,生成虛擬表VT1-J1。
  • ON篩選器。  這個階段對上個步驟生成的VT1-J1進行篩選,根據ON子句中出現的謂詞進行篩選,讓謂詞取值為true的行通過了考驗,插入到VT1-J2。
  • 添加外部行。如果指定了OUTER JOIN,還需要將VT1-J2中沒有找到匹配的行,作為外部行添加到VT1-J2中,生成VT1-J3。

經過以上步驟,FROM階段就完成了。概括地講,FROM階段就是進行預處理的,根據提供的運算符對語句中提到的各個表進行處理(除了JOIN,還有APPLY,PIVOT,UNPIVOT)。

2. WHERE階段

 WHERE階段是根據<where_predicate>中條件對VT1中的行進行篩選,讓條件成立的行才會插入到VT2中。

3. GROUP BY階段

GROUP階段按照指定的列名列表,將VT2中的行進行分組,生成VT3。最后每個分組只有一行。

4. HAVING階段

該階段根據HAVING子句中出現的謂詞對VT3的分組進行篩選,並將符合條件的組插入到VT4中。

5. SELECT階段

這個階段是投影的過程,處理SELECT子句提到的元素,產生VT5。這個步驟一般按下列順序進行:

  • 計算SELECT列表中的表達式,生成VT5-1。
  • 若有DISTINCT,則刪除VT5-1中的重復行,生成VT5-2。
  • 若有TOP,則根據ORDER BY子句定義的邏輯順序,從VT5-2中選擇簽名指定數量或者百分比的行,生成VT5-3。

6. ORDER BY階段

根據ORDER BY子句中指定的列明列表,對VT5-3中的行,進行排序,生成游標VC6。

三、樣例解釋

查詢語句1的執行過程

SELECT * FROM A LEFT JOIN ORACLE.B ON A.PERSON_ID = B.PERSON_ID AND A.PERSON_ID = 1;

求笛卡爾積,產生5*5=25條記錄

A.PERSON_ID

PERSON_NAME

B.PERSON_ID

LOVE_FRUIT

1

張三

1

香蕉

1

張三

2

蘋果

1

張三

3

橘子

1

張三

4

1

張三

8

2

李四

1

香蕉

2

李四

2

蘋果

2

李四

3

橘子

2

李四

4

2

李四

8

3

王五

1

香蕉

3

王五

2

蘋果

3

王五

3

橘子

3

王五

4

3

王五

8

4

趙六

1

香蕉

4

趙六

2

蘋果

4

趙六

3

橘子

4

趙六

4

4

趙六

8

5

周七

1

香蕉

5

周七

2

蘋果

5

周七

3

橘子

5

周七

4

5

周七

8

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ON篩選器(A.PERSON_ID=B.PERSON_ID AND A.PERSON_ID=1)

A.PERSON_ID

PERSON_NAME

B.PERSON_ID

LOVE_FRUIT

1

張三

1

香蕉

 

 

 

 

添加外部行

A.PERSON_ID

PERSON_NAME

B.PERSON_ID

LOVE_FRUIT

1

張三

1

香蕉

1

張三

 

 

1

張三

 

 

1

張三

 

 

1

張三

 

 

 

 

 

 

 

 

 

 

 

查詢語句2的執行過程

SELECT * FROM A LEFT JOIN ORACLE.B ON A.PERSON_ID = B.PERSON_ID WHERE A.PERSON_ID = 1;

求笛卡爾積,產生5*5=25條記錄

A.PERSON_ID

PERSON_NAME

B.PERSON_ID

LOVE_FRUIT

1

張三

1

香蕉

1

張三

2

蘋果

1

張三

3

橘子

1

張三

4

1

張三

8

2

李四

1

香蕉

2

李四

2

蘋果

2

李四

3

橘子

2

李四

4

2

李四

8

3

王五

1

香蕉

3

王五

2

蘋果

3

王五

3

橘子

3

王五

4

3

王五

8

4

趙六

1

香蕉

4

趙六

2

蘋果

4

趙六

3

橘子

4

趙六

4

4

趙六

8

5

周七

1

香蕉

5

周七

2

蘋果

5

周七

3

橘子

5

周七

4

5

周七

8

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

ON篩選器 (A.PERSON_ID=B.PERSON_ID)

A.PERSON_ID

PERSON_NAME

B.PERSON_ID

LOVE_FRUIT

1

張三

1

香蕉

2

李四

2

蘋果

3

王五

3

橘子

4

趙六

4

 

 

 

 

 

 

 

 

添加外部行

A.PERSON_ID

PERSON_NAME

B.PERSON_ID

LOVE_FRUIT

1

張三

1

香蕉

2

李四

2

蘋果

3

王五

3

橘子

4

趙六

4

5

周七

 

 

 

 

 

 

 

 

 

 

 

WHERE階段 (A.PERSON_ID=1)

A.PERSON_ID

PERSON_NAME

B.PERSON_ID

LOVE_FRUIT

1

張三

1

香蕉

 

 

 

有了上面的驗證,我們可以猜測下面語句的執行結果

SELECT * FROM  A LEFT JOIN ORACLE.B ON A.PERSON_ID = B.PERSON_ID;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM