邏輯有點難理解的Sql執行結果,以及用處

ljm0211發表於2012-06-20
準備測試環境:
create table kevintest (col1 char(1),col2 char(2),col3 int);
insert into kevintest values('A','B',2);
insert into kevintest values('A','B',3);
insert into kevintest values('A','B',4);
insert into kevintest values('A','C',1);
insert into kevintest values('A','C',2);
insert into kevintest values('A','C',3);
insert into kevintest values('A','C',4);
insert into kevintest values('A','C',5);
邏輯有點難理解的Sql執行結果,以及用處

分析物件:
SELECT *
FROM kevintest c
WHERE col1 = 'A' AND col3 = (SELECT MAX (col3)
                                FROM kevintest
                               WHERE col1 = c.col1 AND col2 = c.col2)
執行結果:
邏輯有點難理解的Sql執行結果,以及用處

理解執行邏輯,先從kevintest c Table中以條件col1='A'取得記錄集,針對記錄集中每條記錄(例如記錄“AB3”),使用條件col3=(……),同時每條記錄中“AB”的值又作為了子查詢中的條件,透過子查詢取得結果後再對記錄“AB3”進行過濾,在本例中“AB”傳入子查詢取得結果為“4”,對"AB3"進行過濾會將"AB3這條記錄過濾掉,因為這條記錄不滿足col3=4(子查詢結果)。
依次分析記錄,發現"AB4"會被留下作為查詢結果的一條記錄。“AC5”會被留下作為查詢結果的一條記錄。
透過結果我們可以看出,在子查詢中傳入相同表的col1和col2進行連線並對結果使用集合函式時,實際SQL取得的結果相當於在表kevintest中對col1和col2做group by的操作,取得每個結果組中col3最大(或其他聚合函式)的記錄。
這個group by col1,col2操作從Sql Server顯示的執行計劃中也可以看到。SQL:select col1,col2,max(col3) from kevintest group by col1,col2,能得到與分析物件相同的結果。不過在某些情況下這句SQL還無法代替分析物件的寫法。因為我們知道在使用聚合函式時,select後面不能接group by和聚合函式操作的物件之外的列。如果試驗Table中在有col4,select col1,col2,col4,max(col3) from kevintest group by col1,col2,這樣寫法就會報錯。而分析物件就可以避免這個問題。
結論:
分析物件:
SELECT *
FROM kevintest c
WHERE col1 = 'A' AND col3 = (SELECT MAX (col3)
                                FROM kevintest
                               WHERE col1 = c.col1 AND col2 = c.col2)
在Table kevintest中取得以col1和col2分組的各組中col3最大的記錄,所得記錄數等於以col1和col2分組所得到的組的個數。

PS:實現與分析物件相同功能還有一個寫法,這種寫法看起來好理解一些,不過Sql Server的寫法看起來沒有分析物件簡潔,還要考慮各個列的型別轉換。不過Oracle的寫法不用考慮型別轉換的問題,不過Oracle的問題在與這種寫法在Sql Server裡是有語法錯誤的。
Sql Server寫法:
SELECT *
FROM kevintest c
WHERE col1 = 'A' AND col1+'|'+col2+'|'+CHAR(col3) in (SELECT col1+'|'+col2+'|'+CHAR(MAX (col3))
                                FROM kevintest group by col1,col2)
Oracle寫法:
SELECT *
FROM kevintest c
WHERE col1 = 'A' AND (col1,col2,col3) in (SELECT col1,col2,MAX (col3)
                                FROM kevintest group by col1,col2)

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/11411056/viewspace-733359/,如需轉載,請註明出處,否則將追究法律責任。

相關文章