通過ORACLE分析函式過濾重複資料

2021-09-21 20:50:33 字數 2526 閱讀 9826

今天,確切的講應該是昨天下午,研發的同事突然向我尋求sql技術支援。

看看他的問題,比較麻煩些。

select sbl.fee_terminal_id , sbl.status, smr.status, smr.report_time

from ***_log sbl, ***_report smr

where sbl.task_id 

in ('8888','9999','1111','2222')

and sbl.msg_id=smr.msg_id(+)

and sbl.submit_time>=

'20080927'

and sbl.submit_time<=

'20080929'

and smr.report_time>=

'20080927'

and smr.report_time<=

'20080929'

and (fee_terminal_id, report_time) 

in (

select

distinct(sbl.fee_terminal_id), 

max(smr.report_time)

from ***_log sbl, ***_report smr

where sbl.task_id 

in (

'8888',

'9999',

'1111',

'2222')

and sbl.msg_id=smr.msg_id(+)

and sbl.submit_time>=

'20080927'

and sbl.submit_time<=

'20080929'

and smr.report_time>=

'20080927'

and smr.report_time<=

'20080929'

group

by fee_terminal_id

);他需要提取某個時間段內,某個id(fee_terminal_id)最新時間的狀態。其實如果是在一張表中,直接max(report_time)就可以了。但是,恰恰這是兩張表。每張表中乙個狀態,通常的情況就是我們首先得到id及其最大的(最新)報告時間,然後再「自連線」自己進行where條件的查詢。

上面的sql就是通過這種基本的想法來實現的。

一般情況下,應該是沒有問題的。但是,這次問題卻出現了。主要就是資料太大,執行了30分鐘沒有看到有結果集返回。

首先因為兩張基本表(***_log sbl, ***_report smr)都是分割槽表,不然資料也不會這麼大呀。進行必要的分割槽工作,要知道,再精良的sql,資料太多也會有問題。優化的第一步就是「少做」(片面一點講,效能真的是設計出來的)。

完成後,直接執行原始sql,基本上180秒左右,可以看到結果集返回。

至此,都有些「跑題」,還有過濾重複呢(其實就是找出最新時間的id狀態即可)。

看著這句sql我總是有些不死心,看看其實這句sql的兩個部分的sql語句基本相同,其實一部分就可以得到所有資訊,就是因為資料無法得到id和最新時間對應的值在一句話中。

突然想起了oracle的分析函式。ok,使用

lagselect a,b,c,d

from (

select sbl.fee_terminal_id a,

sbl.status b,

smr.status c,

smr.report_time d,

lag(sbl.fee_terminal_id,1,0) 

over(partition 

by sbl.fee_terminal_id 

order

by smr.report_time 

desc) flag

from ***_log sbl, ***_report smr

where sbl.task_id 

in (

'8888',

'9999',

'1111',

'2222')

and sbl.msg_id = smr.msg_id(+)

and sbl.submit_time >= 

'20080927'

and sbl.submit_time <= 

'20080929'

and smr.report_time >= 

'20080927'

and smr.report_time <= 

'20080929')

where flag = 0

優化了原sql語句。

執行成本從19106下降到10139,結果集返回的時間下降到15秒左右。響應時間有大幅提高。

總結:此次優化的核心思想,減少sql的重複執行,能在一句sql中執行完成的,就不要放到兩句或者是多個子查詢中執行。

通過使用分析函式lag,將分類和排序一次完成。一定要多多嘗試使用分析函式,往往會給你帶來非常的驚喜。

btw,國慶節快樂。-:)

本文**

larry.yue

PHP引數過濾的函式

stripslashes stripslashes 反引用乙個引用字串 說明string stripslashes string str 反引用乙個引用字串。note 如果 magic quotes sybase 項開啟,反斜線將被去除,但是兩個反斜線將會被替換成乙個。乙個使用範例是使用 php 檢...

C 通用函式 過濾string的空行

需要過濾string中的空行,可以網上搜尋未果。最終自己寫了乙個較為通用的函式。輸入s表示要過濾的string lineend表示行結束符,不同平台的行結束符可能不同。win和linux是nl lf n mac平台則以cr r 結尾。std string deletespacelineofstr c...

精通LINQ 8 2 7 使用函式過濾資料

linq to sql 不但能夠呼叫儲存過程查詢或運算元據庫中的資料,而且還可以呼叫函式處理資料庫中的資料。和 linq to sql 呼叫儲存過程一樣,它也將為函式建立乙個方法,並指定該方法呼叫的函式,以及傳入的引數和返回值。下面的 例項在 linqdbdatacontext 類中建立 fu fi...