當我們面對一個數據表,且表結構為:
~~~
<span style="font-size:18px;">create table R_ExtSubFina_Month
(
rptdate date not null,
rptname varchar2(10) not null,
rptNum varchar2(10) not null,
SaleMoney number(18,3),
proMoney number(18,3),
,Status varchar2(2)
);</span>
~~~
現在表中已經存在的數據如下(PS:這里的報送編碼需要從別的表中獲取):

但是我們需要從當前表中統計出今年的本月,去年的本月和今年上個月的銷售額和定金的數據,那么我們的sql語句應該怎么寫??
方案一:union
我們都知道union是對表格進行聯合查詢的,當我們需要對兩個表的數據進行查詢我們可以使用,但是要遵守:
1.要求我們獲取兩個表的字段個數和字段數據類型是要完全一致的;
2.如果數據類型一致,但是個數不一致,我們可以對某個表中設計空字段,比如需要查詢A表中的兩個字段,需要B表中的1個字段,那么我們就要將語句這樣寫:
? ? ? ? ?select * from A
? ? ? ? ? ? ?union?
? ? ? ? select a, ' ?' from B?
此處的 ?‘ ?’ 就保證了A 和B表的字段數量一致;
但是我們的sql語句不單單是為了查詢結果,對結果進行顯示和分析,更重要的是性能;所以union不能入圍我們的選擇方案(具體原因稍后在方案2中講解)
方案二:union all
使用union 需要將兩個表的字段數量和字段的數據類型都一致,為了避免這種問題,我們使用union all,這樣我們可以直接將上面的語句修改為:
select * from A ?union all(select * from B);
雖然可以解決這個查詢的問題,但是顯示的結果中需要三個不同日期的結果,而這三個日期需要我們手動進行加減計算,然后再同一個表的同一個字段中取不同的值,那么問題來了,當我們使用union all ?我們需要以每一個日期作為條件對表進行查詢,這樣就對表進行了至少三次的掃描,所以我們需要擔心這樣的語句帶來的性能問題;
那么相比方案一我們有沒有一些進步呢?答案是有的;
Union:對兩個結果集進行并集操作,不包括重復行,同時進行默認規則的排序;?
Union All:對兩個結果集進行并集操作,包括重復行,不進行排序;
Union因為要進行重復值掃描,所以效率低。如果合并沒有刻意要刪除重復行,那么就使用Union All
方案三:decode轉碼求和
原理:我們將每一個日期作為條件一次性將所有的數據都查詢出來,這樣我們會查詢出來三條數據,詳細如下:

我們可以發現紅色框內的數據有為0的數據,這樣我們想要的數據已經呈現出來,但是我們如何把三條數據合成一條(不含0)呢??
思路: 行專列-->decode-->求和
我們將上面的數據看成一個矩陣,矩陣行專列之后結果是不變的,所以上圖中的數據就會變成下圖中的數據:

這樣我們可以對每一列求和,然后和剛才的三個日期進行合并,這樣三條數據就會被我們合成一條;
實現代碼如下:
PS:參數設置:l_year :當前的年月 ; l_curLastMonth :今年的上個月; ?l_lastYear :去年的這個月
~~~
<span style="font-size:18px;">select l_year year, l_curLastMonth lmon,l_lastYear lymon,
decode(A.rptdate,l_year,A.saleMoney ,0) AS ,
decode(A.rptdate, l_curLastMonth,A.saleMoney ,0) ASS,
decode(A.rptdate,l_lastYear,A.saleMoney ,0) ASSS
from A </span>
~~~
到這里我們已經得到我們想要的數據,還挺簡單的吧,以上只是一點小積累,有不對的地方歡迎大家指點。Oracle的sql語句正在進一步的總結,如果有什么好的建議或者意見請大家留言!!
? 
? ??