方案3的思路比較值得學習挺峡,我們將層層剖析它的結(jié)構:
1:對每一條記錄找它的前一行
所謂連續(xù)的序列號就是看相同格式的情況下前一行記錄與當前行的記錄序號的值是否相差為1:
如果相差為1竿滨,則說明兩個序列號是連續(xù)的抠忘;
如果不為1蹦骑,則兩個序列號不是連續(xù)的
select numFormat,
lag(code, 1) over(partition by numFormat order by code) previousCode, code,
max(code) over(partition by numFormat) maxn
from inventory例隆;
?2:過濾掉中間連續(xù)序列號愈诚。
這里通過比較當前序列號與前一行的序列號相減是非相差為1淹辞,相差為1將被過濾掉;相差不為1比如2或者說有null值則不被過濾竭翠。
select * from(
select numFormat,
lag(code, 1) over(partition by numFormat order by code) previousCode, code,
max(code) over(partition by numFormat) maxn
from inventory
)
where nvl(code-previousCode-1,1) <> 0
;
?3:把當前行的code列作為 startNum,后一行的previouscode列作為endNum
select numFormat,code startNum, lead(previousCode) over(partition BY numFormat order by previousCode ) endNum from(
select numFormat,
lag(code, 1) over(partition by numFormat order by code) previousCode, code,
max(code) over(partition by numFormat) maxn
from inventory
)
where nvl(code-previousCode-1,1) <> 0
;
但是我們這里卻得到了錯誤的結(jié)果振坚。
這里面有兩個問題:
使用lead函數(shù)往后找的過程中,如果當前行已經(jīng)是最后一行斋扰,則應該使用最大數(shù)字作為endNum渡八,所以需要使用nvl函數(shù)來判斷是否為null啃洋。
本該是第一行的的記錄跑startNum為1的居然放到了最后一行。經(jīng)過調(diào)查屎鳍,previousCode的值存在為null的情況宏娄,oracle通常遇到為null值是把null放在最后,所以我們需要添加previousCode為null的行要排在前面逮壁。使用nulls first.
4:修復第3步的問題绝编。
select numFormat,code startNum,?nvl(lead(previousCode) over(partition BY numFormat order by previousCode?nulls first?),maxn) endNum from(
select numFormat,
lag(code, 1) over(partition by numFormat order by code) previousCode, code,
max(code) over(partition by numFormat) maxn
from inventory
)
where nvl(code-previousCode-1,1) <> 0
;
注意紅色部分的修改,這樣就可以得到如下正確的結(jié)果貌踏。