程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> 其他數據庫知識 >> MSSQL >> SQL語句的各個症結字的解析進程具體總結

SQL語句的各個症結字的解析進程具體總結

編輯:MSSQL

SQL語句的各個症結字的解析進程具體總結。本站提示廣大學習愛好者:(SQL語句的各個症結字的解析進程具體總結)文章只能為提供參考,不一定能成為您想要的結果。以下是SQL語句的各個症結字的解析進程具體總結正文


因為比來須要做一些sql query機能晉升的研討,是以研討了一下sql語句的處理進程。在園子裡看了下,年夜家寫了許多相干的文章,年夜家的著重點各有分歧。本文是我在看了各類材料背工機總結的,會具體的,一步一步的講述一個sql語句的各個症結字的解析進程,迎接年夜家相互進修。

SQL語句的解析次序

簡略的說一個sql語句是依照以下的次序解析的:

1. FROM FROM前面的表標識了這條語句要查詢的數據源。和一些子句如,(1-J1)笛卡爾積,(1-J2)ON過濾,(1-J3)添加內部列,所要運用的對象。FROM進程以後會生成一個虛擬表VT1。
(1-J1)笛卡爾積 這個步調管帳算兩個相干聯表的笛卡爾積(CROSS JOIN) ,生成虛擬表VT1-J1。
(1-J2)ON過濾 這個步調基於虛擬表VT1-J1這一個虛擬表停止過濾,過濾出一切知足ON 謂詞前提的列,生成虛擬表VT1-J2。
(1-J3)添加內部行  假如應用了外銜接,保存表中的不相符ON前提的列也會被參加到VT1-J2中,作為內部行,生成虛擬表VT1-J3。 
2. WHERE 對VT1進程中生成的暫時表停止過濾,知足where子句的列被拔出到VT2表中。
3. GROUP BY 這個子句會把VT2中生成的表依照GROUP BY中的列停止分組。生成VT3表。
4. HAVING 這個子句對VT3表中的分歧的組停止過濾,知足HAVING前提的子句被參加到VT4表中。
5. SELECT 這個子句對SELECT子句中的元素停止處置,生成VT5表。
(5-1)盤算表達式 盤算SELECT 子句中的表達式,生成VT5-1
(5-2)DISTINCT 尋覓VT5-1中的反復列,並刪失落,生成VT5-2
(5-3)TOP 從ORDER BY子句界說的成果中,挑選出相符前提的列。生成VT5-3表
ORDER BY 從VT5-3中的表中,依據ORDER BY 子句的前提對成果停止排序,生成VC6表。

客戶,定單的查詢例子

起首創立一個Customers表,拔出以下數據:

customerid city FISSA Madrid FRNDO Madrid KRLOS Madrid MRPHS Zion

創立一個Orders表,拔出以下數據:

orderid customerid 1 FRNDO 2 FRNDO 3 KRLOS 4 KRLOS 5 KRLOS 6 MRPHS 7 NULL

假設我們想要查詢來自Madrid的,定單數小於3的客戶,並把他們的定單數顯示出來,成果依照定單數從小到年夜停止排序。

SELECT C.customerid, COUNT(O.orderid) AS numorders
FROM dbo.Customers AS C
LEFT OUTER JOIN dbo.Orders AS O
ON C.customerid = O.customerid
WHERE C.city = 'Madrid'
GROUP BY C.customerid
HAVING COUNT(O.orderid) < 3
ORDER BY numorders

查詢成果為:

customerid numorders FISSA 0 FRNDO 2

上面我們會具體的講述sql是如何盤算出這個成果的:

FROM子句

FROM子句標識了須要查詢的表,假如指定了表操作,會從左到右的處置,每個基於一個或許兩個表的表操作都邑前往一個輸入表。右邊表的輸入成果會作為下一個表操作的輸出成果。例如,交表相干的操作有 (1-J1)笛卡爾積,(1-J2)ON過濾器,(1-J3)添加內部列。FROM句子生成虛擬表VT1。

Step 1-J1:履行笛卡爾積(CROSS JOIN)

笛卡爾積會把閣下兩個表每行一切能夠的組合都列出來生成表VT1-J1,假如左表有m列,右表有n列,那末笛卡爾積以後生成的VT1-J1表將會有m×n列。

Step 1-J1這個步調等價於履行:

SELECT * from Customers C CROSS JOIN Orders O

履行成果為:(共有4×7列)

C.customerid C.city O.orderid O.customerid FISSA Madrid 1 FRNDO FISSA Madrid 2 FRNDO FISSA Madrid 3 KRLOS FISSA Madrid 4 KRLOS FISSA Madrid 5 KRLOS FISSA Madrid 6 MRPHS FISSA Madrid 7 NULL FRNDO Madrid 1 FRNDO FRNDO Madrid 2 FRNDO FRNDO Madrid 3 KRLOS FRNDO Madrid 4 KRLOS FRNDO Madrid 5 KRLOS FRNDO Madrid 6 MRPHS FRNDO Madrid 7 NULL KRLOS Madrid 1 FRNDO KRLOS Madrid 2 FRNDO KRLOS Madrid 3 KRLOS KRLOS Madrid 4 KRLOS KRLOS Madrid 5 KRLOS KRLOS Madrid 6 MRPHS KRLOS Madrid 7 NULL MRPHS Zion 1 FRNDO MRPHS Zion 2 FRNDO MRPHS Zion 3 KRLOS MRPHS Zion 4 KRLOS MRPHS Zion 5 KRLOS MRPHS Zion 6 MRPHS MRPHS Zion 7 NULLStep 1-J2:運用ON過濾,(JOIN 前提)

ON過濾前提是sql的三個過濾前提(ON,WHERE,HAVING)中最早履行的,ON過濾前提運用於前一步生成的虛擬表(VT1-J1),知足ON過濾前提的行會被參加到虛擬表VT1-J2中。在運用了ON 過濾以後,生成的VT1-J2表以下所示:

C.customerid C.city O.orderid O.customerid FRNDO Madrid 1 FRNDO FRNDO Madrid 2 FRNDO KRLOS Madrid 3 KRLOS KRLOS Madrid 4 KRLOS KRLOS Madrid 5 KRLOS MRPHS Zion 6 MRPHSStep 1-J3:添加內部列

這個步調只會湧現在應用了外銜接的情形。關於外銜接(LEFT,RIGHT, or FULL),你可以標志一個或許兩個表作為保存表。作為保存表意味著你願望這個內外面的一切列都被前往,即便它外面的數據不知足ON子句的過濾前提。LEFT OUTER JOIN 把右邊的表標志為保存表,RIGHTOUTER JOIN把左邊的表作為保存表,FULL OUTER JOIN把兩個表都標志為保存表.Step 1-J3為依據VT1-J2中的虛擬表,添加了保存表中不知足ON 前提的列,在未保存表中沒有對應的列,是以標志為NULL。這個進程生成了虛擬表VT1-J3。

C.customerid C.city O.orderid O.customerid FISSA Madrid NULL NULL FRNDO Madrid 1 FRNDO FRNDO Madrid 2 FRNDO KRLOS Madrid 3 KRLOS KRLOS Madrid 4 KRLOS KRLOS Madrid 5 KRLOS MRPHS Zion 6 MRPHS

假如FROM子句中有多個表操作運算,sql會依照從左到右的次序處置,右邊生成的暫時表成果作為左邊表的輸出表。

Step 2 WHERE 子句

WHERE過濾被運用到前一步生成的暫時表中,依據WHERE過濾前提生成暫時表VT2。

留意:因為數據如今還沒有被分組,是以如今你不克不及應用聚合運算-例如:你不克不及應用如許的句子 WHERE orderdate = MAX(orderdate)。別的你也不克不及應用SELECT子句中創立的變量別號,由於如今還沒有處置SELECT子句-例如你不克不及寫如許的句子:SELECT YEAR(orderdate) AS orderyear . . . WHERE orderyear > 2008.

運用這個過濾

WHERE C.city = 'Madrid'

這時候生成的暫時表VT2的內容以下:

C.customerid C.city O.orderid O.customerid FISSA Madrid NULL NULL FRNDO Madrid 1 FRNDO FRNDO Madrid 2 FRNDO KRLOS Madrid 3 KRLOS KRLOS Madrid 4 KRLOS KRLOS Madrid 5 KRLOS

在這個例子中,你須要在ON子句中應用ON C.customerid = O.customerid過濾,沒有定單的客戶在1-J2這一步中被過濾失落,然則在1-J3這一步中作為內部列又被加回來。然則,因為你只想前往來自Madrid的客戶,是以你須要在WHERE子句中過濾城市(WHERE C.city = ‘Madrid'),假如你放在ON過濾中,不屬於Madrid的客戶在添加內部列中會被添加回來。

關於ON 和 WHERE 的差別須要在這裡解釋一下,ON 和WHERE 的重要差別在於 ON 其實添加內部列之進步行過濾,WHERE 是在以後。ON過濾失落的列會在1-J3中添加回來。假如你不須要添加內部列,那末這兩個過濾是雷同的。

Step 3 GROUP BY子句

這個子句會把前一步中生成的暫時表中的數據停止分組,每行都邑分到而且只分到一個組裡,生成虛擬表VT3。VT3表中包括了VT2表中一切的數據,和分組標識符。

這是生成的暫時表VT3的內容以下:

Groups
C.customerid C.customerid C.city O.orderid O.customerid FISSA FISSA Madrid NULL NULL FRNDO FRNDO Madrid 1 FRNDO FRNDO Madrid 2 FRNDO   KRLOS Madrid 3 KRLOS KRLOS KRLOS Madrid 4 KRLOS   KRLOS Madrid 5 KRLOS

sql終究前往的成果中,每個分組必需只能前往一行(除非被過濾失落),是以當一個sql語句中應用了GROUP BY時,在GROUP BY前面處置的子句,如SELECT,HAVING子句等,只能應用湧現在GROUP BY前面的列,關於沒有湧現GROUP BY前面的列必需應用聚合函數(如 MAX ,MIN,COUNT,AVG等),包管每個GROUP只前往一行。

Step 4 HAVING子句

HAVING子句用來過濾前一步生成的暫時表,而且只感化於分組後的數據,知足HAVING前提的GROUP被添加到虛擬表VT4中。

當運用了這個過濾:

HAVING COUNT(O.orderid) < 3

以後,生成的VT4表內容以下:

Groups
C.customerid C.customerid C.city O.orderid O.customerid FISSA FISSA Madrid NULL NULL FRNDO FRNDO Madrid 1 FRNDO   FRNDO Madrid 2 FRNDO

須要留意的一點是,這外面應用的是COUNT(O.orderid),而不是COUNT(*),因為這個查詢中添加了內部列,COUNT辦法會疏忽NULL的列,招致湧現了你不想要的成果。

Step 5 SELECT 子句

雖然湧現在sql語句的最後面,SELECT在第五步的時刻才被處置,SELECT子句前往的表會終究前往給挪用者。這個子句包括三個子階段:(5-1)盤算表達式,(5-2) 處置DISTINCT,(5-3)運用TOP過濾。

Step 5-1 盤算表達式

SELECT子句中的表達式可以前往或許操作前一步表中前往的根本列。假如這個sql語句是一個聚合查詢,在Step 3以後,你只能應用GROUP BY中的列,對不屬於GROUP聚集中的列必需應用聚合運算。不屬於FROM表中根本列的必需為其起一個體名,如YEAR(orderdate) AS orderyear。

留意:在SELECT子句中創立的別號,不克不及在之前的Step中應用,即便在SELECT子句中也不克不及。緣由是sql的許多操作是同時操作(all at once operation),至於甚麼是all-at-once operation這裡就不再引見了。是以,SELECT子句中創立的別號只能在前面的子句中應用,如ORDER BY。例如:SELECT YEAR(orderdate) AS orderyear . . . ORDER BY orderyear。

在這個例子中:

SELECT C.customerid, COUNT(O.orderid) AS numorders

成果會獲得一個虛擬表VT5-1:

C.customerid numorders FIFSSA 0 FRNDO 2

Step 5-2:運用DISTINCT子句

假如sql語句中應用了DISTINCT,sql會把反復列去失落,生成虛擬表VT5-2。

Step 5-3:運用TOP選項

TOP選項是T-SQL供給的一個功效,用來表現顯示若干行。基於ORDER BY子句界說的次序,指定個數的列會被查詢出來。這個進程生成虛擬表VT5-3。

正如上文提到的,這一步依附於ORDER BY界說的次序來決議哪些列應當顯示在後面。假如你沒有指定成果的ORDER BY次序,也沒有應用WITH TIES子句 ,每次的前往成果能夠會紛歧致。

在我們的例子中,Step 5-3被省略了,由於我們沒有應用TOP症結字。

Step 6:ORDER BY子句

前一步前往的虛擬表在這一步被排序,依據ORDER BY子句指定的次序,前往游標VC6。ORDER BY子句也是獨一一個可使用SELECT子句創立的別號的處所。

留意:這一步和之前分歧的處所在於,這一步前往的成果是一個游標,而不是表。sql是基於聚集實際的,一個聚集沒有對他的行界說次序,它只是一個成員的邏輯聚集,是以成員的次序其實不主要。帶有ORDER BY子句的sql前往一個依照特定序列組織每行的對象。ANSI 把如許的一個對象叫游標。懂得這一點對你懂得sql很主要。

 下面的步調如圖所示:

image

本書中重要內容是參照 Inside Microsoft SQL Server 2008:T-SQL Query,中的內容,年夜家假如想深刻懂得sql查詢相干的常識,可以找這本書看看,我這有英文原版的pdf,須要的可以找我要。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved