星期五, 4月 05, 2013

[SQL] T-SQL 語法邏輯順序

T-SQL 執行時有其邏輯順序,根據不同的順序會產生不一樣的結果。
    SELECT 陳述式的邏輯處理順序(截取 MSDN 內容)
下列步驟顯示 SELECT 陳述式的邏輯處理順序或繫結順序。此順序會決定在某個步驟中定義的物件提供給後續步驟之子句使用的時間。例如,如果查詢處理器可繫結至 (存取) FROM 子句中定義的資料表或檢視表,這些物件及其資料行就會提供給所有後續步驟使用。反之,因為 SELECT 子句是步驟 8,所以前面的子句無法參考該子句中定義的任何資料行別名或衍生資料行。 不過,ORDER BY 子句等後續子句都可以參考它們。請注意,陳述式的實際執行方式由查詢處理器決定,其順序可能與此清單不同。
  1. FROM
  2. ON
  3. JOIN
  4. WHERE
  5. GROUP BY
  6. WITH CUBE 或 WITH ROLLUP
  7. HAVING
  8. SELECT
  9. DISTINCT
  10. ORDER BY
  11. TOP

  • Sample Data
利用每個學生擁有的書籍來說明
DECLARE @STD TABLE (STDNO char(3),STDName char(10))
INSERT INTO @STD VALUES('001','張三')
INSERT INTO @STD VALUES('002','李四')
INSERT INTO @STD VALUES('003','王五')

DECLARE @Books TABLE (ID int,STDNO char(3) , Kind char(10) , BookName char(30))
INSERT INTO @Books VALUES(1,'001','SQL','SQL Server T-SQL')
INSERT INTO @Books VALUES(2,'001','SQL','SQL Server Turning')
INSERT INTO @Books VALUES(3,'001','SQL','SQL Server Statistics')
INSERT INTO @Books VALUES(4,'003','Win','Windows Server')
INSERT INTO @Books VALUES(5,'003','SQL','SQL Server T-SQL')
INSERT INTO @Books VALUES(6,'003','Win','HyperV')
  • 欄位別名的使用
利用兩個簡單範例來說明上述邏輯順序
-- 簡易範例 1
SELECT STDNO AS 學生編號 , STDName AS 學生姓名
FROM @STD
ORDER BY 學生編號 DESC -- 利用欄位別名來排序
ORDER BY 的順序在 SELECT 之後,因此 ORDER BY 可以指定 SELECT 的欄位別名,當成排序的欄位選擇。
-- 簡易範例 2
SELECT STDNO AS 學生編號 , STDName AS 學生姓名
FROM @STD
WHERE 學生編號 = '001' -- 會出現此錯誤訊息"無效的資料行名稱 '學生編號'"。
WHERE 的邏輯順序,因為在 SELECT 之前,所以 WHERE 條件內不可以指定欄位別名來當成條件
  • LEFT JOIN 篩選條件位置(ON 或 WHERE)的差異
計算每個學生擁有關於 SQL 的書籍有多少本,沒有的學生必須秀 0 來表示。
-- WHERE 內條件判斷
SELECT 
  A.STDNO AS 學生編號 , 
  COUNT(B.BookName) AS 書籍數量
FROM @STD AS A 
  LEFT JOIN @books AS B ON A.STDNO = B.STDNO
WHERE B.Kind = 'SQL'
GROUP BY A.STDNO

-- ON 內條件判斷
SELECT 
  A.STDNO AS 學生編號 , 
  COUNT(B.BookName) AS 書籍數量
FROM @STD AS A 
  LEFT JOIN @books AS B ON A.STDNO = B.STDNO AND B.Kind = 'SQL' 
GROUP BY A.STDNO

在 WHERE 內判斷,是在 LEFT JOIN 後產生結果後(下圖),再對其結果(下圖)進行條件判斷


ON 內判斷是先針對 @Book 內進行條件判斷,再把判斷後結果(下圖)跟 @STD 進行 LEFT JOIN 結合

LEFT JOIN 或 RIGHT JOIN 才會有此邏輯順序問題,JOIN 的話不論是 WHERE 或 ON 中判斷,其結果都是一樣的。
    ON 的備註說明(截取 MSDN 內容)
ON 子句中可以有僅涉及其中一個聯結資料表的述詞。 這類述詞也可以在查詢的 WHERE 子句中。 雖然這類述詞的放置不會影響 INNER 聯結,不過,如果涉及 OUTER 聯結,就可能會造成不同的結果。 這是因為 ON 子句中的述詞會套用至聯結之前的資料表,但在語意上,WHERE 子句則套用至聯結的結果。

沒有留言:

張貼留言