sql實現報表加小計、合計


SQL實現統計報表中的“小計”和“合計”

  

 先來一段概念:

----------------------

 DECODE函數是ORACLE PL/SQL是功能強大的函數之一,目前還只有ORACLE公司的SQL提供了此函數,其他數據庫廠商的SQL實現還沒有此功能。DECODE有什么用途 呢? 先構造一個例子,假設我們想給智星職員加工資,其標准是:工資在8000元以下的將加20%;工資在8000元以上的加15%,通常的做法是,先選出記錄 中的工資字段值? select salary into var-salary from employee,然后對變量var-salary用if-then-else或choose case之類的流控制語句進行判斷。 如果用DECODE函數,那么我們就可以把這些流控制語句省略,通過SQL語句就可以直接完成。如下:select decode(sign(salary - 8000),1,salary*1.15,-1,salary*1.2,salary from employee 是不是很簡潔? DECODE的語法:DECODE(value,if1,then1,if2,then2,if3,then3,...,else),表示如果value 等於if1時,DECODE函數的結果返回then1,...,如果不等於任何一個if值,則返回else。初看一下,DECODE 只能做等於測試,但剛才也看到了,我們通過一些函數或計算替代value,是可以使DECODE函數具備大於、小於或等於功能。

--------------------------

在 開發統計報表的過程中,經常會碰到在查詢到的數據集中,插入一些小計行和合計行。比如在烤煙系統中,幾乎每個統計報表都需要加入“合計”行,還有不少涉及 到煙葉等級的統計報表需要加入各煙葉等級的小計行。我看到不少人(包括我自己)都是在程序中專門寫一些方法來處理的,有的方法還很繁瑣。最近在看SQL Server2000的聯機叢書中才發現,利用GROUPING聚合函數和ROLLUP運算符可以輕松實現統計中加入小計和合計功能。

1.      GROUPPINGROLLUP的基本知識

1.1.    GROUPPING

是一個聚合函數,它產生一個附加的列,當用 CUBE 或 ROLLUP 運算符添加行時,附加的列輸出值為1,當所添加的行不是由 CUBE 或 ROLLUP 產生時,附加列值為0。

語法: GROUPING ( column_name )
參數: column_name是 GROUP BY 子句中用於檢查 CUBE 或 ROLLUP 空值的列。
返回類型: int
備注: 分組用於區分由 CUBE 和 ROLLUP 返回的空值和標准的空值。作為CUBE 或 ROLLUP 操作結果返回的 NULL 是 NULL 的特殊應用。

1.2.    ROLLUP

ROLLUP 運算符生成聚合匯總, 需要匯總信息時,此運算很有用運算符生成的結果集類似於 CUBE 運算符生成的結果集。但它們兩者有一些區別,CUBE 生成的結果集顯示了所選列中值的所有組合的聚合。而ROLLUP 生成的結果集顯示了所選列中值的某一層次結構的聚合。

語法: ROLLUP ( column_name1[,column_name2。。。] )
用法: 用在GROUP BY 子句中。對那些需要按其分組,並對其分組的聚合數據進行匯總的列,就請對這些列加上ROLLUP運算符。
注意: “GROUP BY ROLLUP(col1,col2)”與“GROUP BY ROLLUP(col1),ROLLUP(col2)”是有區別的。“GROUP BY ROLLUP(col1),ROLLUP(col2)”其實就相當於“GROUP BY CUBE(col1,col2)”,因為它對每個分組的聚合都要進行匯總。“GROUP BY ROLLUP(col1,col2)”與“GROUP BY ROLLUP(col2,col1)”也有區別,前者是對每個col1的唯一值都產生一個在col1下各個col2聚合值匯總的行,再對所有col1與col2的聚合值產生一個匯總行;而后者是對每個col2的唯一值都產生一個在col2下各個col1聚合值的匯總行,再對所有col1與col2的聚合值產生一個匯總行。這樣說邏輯可能不太清晰,我們看一下下面的圖表就一目了然了。

col1

col2

amount

 

 

 

 

 

 

 

col1

col2

amount

3

2

3584777

3

2

3584777

3

3

12774875

4

2

200789.1

3

 

16359652

5

2

274432

4

2

200789.1

 

2

4059998

4

3

8619498

3

3

12774875

4

 

8820288

4

3

8619498

5

2

274432

5

3

2024463

5

3

2024463

 

3

23418837

5

 

2298895

 

 

27478835

 

 

27478835

 

 

 

GROUP BY ROLLUP(col1,col2)的效果 

GROUP BY ROLLUP(col2,col1)的效果 

 

2.      實際案例

我們現在就來看一個Oracle9i中的統計示例,示例如下:

2.1.    統計要求

開發一個關於各煙葉等級的二次驗級的原發件數、原發重量及驗收重量的統計報表。其中,原發件數、原發重量和驗收重量等列要求計算出各等級組別的小計和所有記錄的合計。

2.2.    我們通常的做法

1.用下面的SQL統計出初步的數據集。

 

SELECT  T1.TOBACCO_CLASS_NAME,
                 T4.TOBACCO_CLASS_TYPE,
                 NVL(SUM(T1.ORG_PIECE), 0) TOTAL_ORG_PIECE,
                 NVL(SUM(T1.ORG_WEIGHT), 0) TOTAL_ORG_WEIGHT,
                 NVL(SUM(T1.AMOUNT), 0) TOTAL_AMOUNT
   FROM  VI_FK_BALANCE_DETAIL T1, TB_TOBACCO_CLASS T4
WHERE  T1.TOBACCO_CLASS_ID=T4.TOBACCO_CLASS_ID
                 AND T1.ACCOUNT_YEAR=T4.ACCOUNT_YEAR
                 AND T4.DEL_FLAG=0
                 AND T4.ENABLE_FLAG=0
                 AND T1.REC_DATE > TO_DATE(‘2006-11-05’, ‘YYYY-MM-DD’
GROUP  BY  T4.TOBACCO_CLASS_TYPE,T1.TOBACCO_CLASS_NAME
  ORDER   BY  T4.TOBACCO_CLASS_TYPE

查詢的結果如下表所示

煙葉等級

等級組別

原發件數

原發重量

驗收重量

(B1F)上桔一

51

4945

197800

197508.1

(B2F)上桔二

51

8335

333400

332316.9

(C1F)中桔一

51

694

27760

27610.54

(C2F)中桔二

51

803

32120

31650.4

(C3F)中桔三

51

6381

255240

255372.6

(X1F)下桔一

51

75

3000

3012.2

(B3F)上桔三

52

4701

188040

187389.9

(B4F)上桔四

52

122

4880

4866.81

(C3V)中微青三

52

174

6960

6934.06

(C4F)中桔四

52

4639

185560

185276.4

(X2F)下桔二

52

1739

69560

69029.79

(X2V)下微青二

52

26

1040

1038.34

(X3F)下桔三

52

1263

50520

50439.86

(X4F)下桔四

53

102

4080

4075.62

(B3K)上雜三

54

0

0

249.39

                            

2.再在程序中編寫相應的方法對查詢得到的數據集進行處理。 我們的重點不是在怎么寫處理數據集的方法上,所以相應的方法在此略去。

 

 

2.3.      SQL直接實現的方法

 

SELECT DECODE(GROUPING(T4.TOBACCO_CLASS_TYPE) + GROUPING(T1.TOBACCO_CLASS_NAME),
                               1,
                               DECODE(T4.TOBACCO_TYPE,
                                                  51, ‘ 上等煙小計 ’,
                                                  52, ‘ 中等煙小計 ’,
                                                  53, ‘ 下等煙小計 ’,
                                                  54, ‘ 低等煙小計 ’,
                                                  ‘ 小計 ’),
                               2,
                               ‘ 合計 ’,
                               T1.TOBACCO_CLASS_NAME
                 ) TOBACCO_CLASS_NAME,
                   T4.TOBACCO_CLASS_TYPE,
                   NVL(SUM(T1.ORG_PIECE),0) TOTAL_ORG_PIECE,
                   NVL(SUM(T1.ORG_WEIGHT), 0) TOTAL_ORG_WEIGHT,
                   NVL(SUM(T1.AMOUNT), 0) TOTAL_AMOUNT
 FROM     VI_FK_BALANCE_DETAIL T1, TB_TOBACCO_CLASS T4
WHERE    T1.TOBACCO_CLASS_ID=T4.TOBACCO_CLASS_ID
                   AND T1.ACCOUNT_YEAR=T4.ACCOUNT_YEAR
                   AND T4.DEL_FLAG=0
                   AND T4.ENABLE_FLAG=0
                   AND T1.REC_DATE > TO_DATE(‘2006-11-05’, ‘YYYY-MM-DD’
GROUP   BY   ROLLUP( T4.TOBACCO_CLASS_TYPE,T1.TOBACCO_CLASS_NAME)
ORDER   BY  T4.TOBACCO_CLASS_TYPE

  

通過查詢得到統計結果如下表所示,該表的統計結果已經滿足了統計要求。

煙葉等級

等級組別

原發件數

原發重量

驗收重量

(B1F)上桔一

51

4945

197800

197508.1

(B2F)上桔二

51

8335

333400

332316.9

(C1F)中桔一

51

694

27760

27610.54

(C2F)中桔二

51

803

32120

31650.4

(C3F)中桔三

51

6381

255240

255372.6

(X1F)下桔一

51

75

3000

3012.2

上等煙小計

51

21233

849320

847470.8

(B3F)上桔三

52

4701

188040

187389.9

(B4F)上桔四

52

122

4880

4866.81

(C3V)中微青三

52

174

6960

6934.06

(C4F)中桔四

52

4639

185560

185276.4

(X2F)下桔二

52

1739

69560

69029.79

(X2V)下微青二

52

26

1040

1038.34

(X3F)下桔三

52

1263

50520

50439.86

等煙小計

52

12664

506560

504975.1

(X4F)下桔四

53

102

4080

4075.62

下等煙小計

53

102

4080

4075.62

(B3K)上雜三

54

0

0

249.39

低等煙小計

54

0

0

249.39

合計

 

33999

1359960

1356771

 

 

    通過比較,相信大家也感覺到后者的獨特魅力了吧。至少我在寫那些對數據集處理得到小計行的方法的時候,感到雖不是很復雜,但也是有些繁瑣的,遠不如直接在SQL中實現小計來得瀟灑、簡潔。


免責聲明!

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



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