關於oracle數據庫中獲取版本號類數據最大值的sql


 目前還在高度加班中,但是本次內容怕自己忘記,好不容易解決的,所以趕緊先隨便抽點時間記錄下,也沒來得及考慮效率什么的優化問題,免得以后忘記了。

測試庫結構如下:

表名為 testtab

字段名為testnum,server

測試數據如下:

獲取最高版本號的數據sql如下:

 1 WITH
 2   L0 as (
 3                     SELECT MAX(to_number(regexp_replace(testnum,'([[:digit:]]+).([[:digit:]]+).([[:digit:]]+)','\1'))) fir  FROM TESTTAB
 4             ),
 5     L1 as (
 6                     SELECT MAX(to_number(regexp_replace(testnum,'([[:digit:]]+).([[:digit:]]+).([[:digit:]]+)','\2'))) sec FROM TESTTAB,L0
 7                     where testnum like fir||'.%'
 8             ),
 9     L2 as (
10                     SELECT MAX(to_number(regexp_replace(testnum,'([[:digit:]]+).([[:digit:]]+).([[:digit:]]+)','\3'))) thr FROM TESTTAB,L1,L0
11                     where testnum like fir||'.'||sec||'.%'
12             )
13 select t3.* from L0,L1,L2,TESTTAB t3 where t3.testnum=fir||'.'||sec||'.'||thr;

最后得出查詢結果:

sql主要用到的函數為with as,該函數主要用處是生成一個公共臨時表,后面可復用,主要思路是分段比較,L0來獲取第一段的最大值,L1在該基礎上獲取第二段的最大值,L2在之前基礎上獲取第三段的最大值,最后將其拼接獲取最大值版本號作為查詢條件去獲取數據。

因為我們版本號是固定格式 A.B.C ,因此可以這樣寫,另外使用的數據庫為oracle,mysql的暫時沒空去考慮。

另外不能直接用oracle的MAX函數去比較,經粗略測試其比較方法類似於去除小數點並右補0進行比較大小,比如

如果確定第一段的數字是確定小於10的一位數,似乎是可以直接使用MAX的,只能說我沒試出反例來,但是也沒空去多試數據,所以不確定行不行


 ---------------------------------------------------------------------------------------------------------------2018-12-13 修訂-------------------------------------------------------------------------------------------------------


 

還是和之前一樣,還在加班中,昨天也就是上面寫的,本身思路是沒問題,分段比較肯定是最穩妥的一個辦法,但是終究因為我sql水平有限,脫離了MAX函數,我不知道該如何將上面的那個sql在我需要的查詢方法里用起來,今天想來想去,終究還是用了最原始的笨辦法,為了能用上max函數,只好這樣了,因為開發時間太緊迫,沒時間給我仔細想別的辦法了,項目畢竟要求12月底上線。

這次的思路是這樣的:利用oracle的字符串處理,將版本號類型數據進行分段處理,每段進行左補0,每段長度補充到3位數一般足夠用了,然后三段拼接,去除小數點,轉為number類型,這樣就可以利用上max函數了。

處理版本號的sql如下:

CREATE OR REPLACE
function dealAppMenuVersion (
        v_in varchar2)
        return number is v_out number(10,0);
        begin
            select to_number( lpad(SUBSTR(v_in, 1, INSTR(v_in,'.',1,1)-1),3,0)
                ||
                lpad(SUBSTR(v_in, INSTR(v_in,'.',1,1)+1, INSTR(v_in,'.',1,2)-INSTR(v_in,'.',1,1)-1),3,0)
                ||
                lpad(SUBSTR(v_in, INSTR(v_in,'.',1,2)+1, LENGTH(v_in)-INSTR(v_in,'.',1,2)),3,0)) into v_out from dual;
            return v_out;
        end;

測試結果如下:

在版本號可以轉化為數字進行正常處理以后,接下來就方便了,先分組,然后根據版本號排序,將每個分組中的最高版本號的那行數據取出來即可。

測試代碼如下:

這里得說說 ROW_NUMBER () OVER (PARTITION BY [field1] order by [field2] asc/desc) 這個oracle提供的函數,很好用,很久以前用過但是我給忘記了,這里自己記錄下防止又忘記了,因為公司mysql用的比較多,oracle用的少函數很容易忘記。

這個函數大致意思上是根據field1進行分組,在該分組上按field2進行排序,還是我剛才的測試數據,效果圖展示如下:

 


免責聲明!

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



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