邏輯有點難理解的Sql執行結果,以及用處
準備測試環境:
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);
分析物件:
SELECT *
FROM kevintest c
WHERE col1 = 'A' AND col3 = (SELECT MAX (col3)
FROM kevintest
WHERE col1 = c.col1 AND col2 = c.col2)
執行結果:
理解執行邏輯,先從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)
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);
分析物件:
SELECT *
FROM kevintest c
WHERE col1 = 'A' AND col3 = (SELECT MAX (col3)
FROM kevintest
WHERE col1 = c.col1 AND col2 = c.col2)
執行結果:
理解執行邏輯,先從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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- SQL Select語句邏輯執行順序SQL
- kubebuilder operator的執行邏輯UI
- 工作284:理解繫結邏輯
- 同樣的sql執行結果不同的原因分析SQL
- 執行結果
- Spark Task 的執行流程④ - task 結果的處理Spark
- 執行ExecBizRule,返回服務更新成功,實際邏輯沒有執行
- oracle邏輯儲存結構理解Oracle
- 使用SQL TRACE和TKPROF觀察SQL語句執行結果SQL
- 執行緒池 execute() 的工作邏輯執行緒
- SAP MM 沒有錄入盤點結果的盤點憑證不能執行MI07
- 儘量用簡單的SQL替代PL/SQL邏輯SQL
- 邏輯難理解版本的輪播圖(實現無縫滾動)
- JDBC中PreparedStatement介面的執行邏輯JDBC
- 沒有運算結果,直接執行完所有程式碼
- SQL Server中TempDB管理(version store的邏輯結構)SQLServer
- 02-邏輯學有什麼用?
- 嘗試修改SQL Server的重做日誌檔案,使其按照修改的結果執行重做,結果失敗SQLServer
- 獲取任務的執行結果
- 解析Oracle執行計劃的結果Oracle
- 理解ProcessFunction的Timer邏輯Function
- oracle 物理讀 邏輯讀的理解Oracle
- oracle 物理讀,邏輯讀的理解Oracle
- oracle的邏輯結構Oracle
- [02] 多執行緒邏輯程式設計執行緒程式設計
- SQL邏輯查詢處理順序特別提醒SQL
- 應用程式邏輯錯誤總結
- 深入分析3種執行緒池執行任務的邏輯方法執行緒
- 創新實訓(八)——題目相關的邏輯處理解釋
- 配置監聽器,建立執行緒定時執行業務邏輯執行緒行業
- Oracle如何進行塊介質的恢復?(有邏輯壞塊是如何處理)Oracle
- 記一次utlrp.sql指令碼執行引發的結果SQL指令碼
- Oracle檢視正在執行的SQL以及執行計劃分析OracleSQL
- 高效的SQL(清晰的邏輯重構業務SQL)SQL
- 多執行緒並行執行,然後彙總結果執行緒並行
- Java獲取多執行緒執行結果方式的歸納與總結Java執行緒
- 主執行緒等待所有其他執行緒執行完畢,然後再繼續執行主執行緒的邏輯,有以下幾種方法可以實現:執行緒
- java程式碼執行字串中的邏輯運算方法Java字串