zoukankan      html  css  js  c++  java
  • oracle 高级分组

    Java代码  收藏代码
      1. 10.高级分组  
      2. 本章目标:  
      3. 对于增强的group by需要掌握:  
      4. 1.使用rollup(也就是roll up累计的意思)操作产生subtotal(小计)的值。  
      5. 2.使用cube操作产生cross-tabulation(列联交叉表)的值。  
      6. 3.使用grouping函数标识通过rollup和cube建立的行的值。  
      7. 4.使用grouping sets产生一个single result set(结果集)。  
      8. 5.使用grouping_id和group_id函数。  
      9. 关键字:rollup(累计,累加),cube(交叉),subtotal(小计),cross-tabulation(列联交叉表,交叉列表)。  
      10.   
      11. 背景知识:  
      12. 我 们知道,通过group by指定列,可以求出按照指定的列一次性统计组的信息,比如求sum,min,max,avg等。然而在实际应用中,比如数据仓 库中,我们需要对数据提供多维分析,对每个维度分析得到汇总数据,提供多角度的数据分析支持。那么单纯使用group by就很难达到这种目标,当然,我 们可以使用union all来将多个维度的分析数据汇总,但是在性能上来说,性能就很低了。所以oracle在8i的时候,提供了增强的 group by的一系列特性。本章就专门研究一下这些特性。  
      13. 注:  
      14. 对于分组的group by,rollup,cube,grouping sets后面的列不必要都出现在查询列中,但是不可出现没有分组的列,这符合SQL的语义要求。  
      15. 数据准备:  
      16. 10.1 多维汇总  
      17.         首先,有一需求:根据all_orders表和region表,计算对应区域每个月的销售额汇总。这个需求很简单,只要通过group by就可以实现,如下:  
      18.        SELECT r.name region,   
      19.        TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month, SUM(o.tot_sales)  
      20. FROM all_orders o JOIN region r  
      21. ON r.region_id = o.region_id  
      22. GROUP BY r.name, o.month;   
      23. 显示数据如下:  
      24. REGION                            MONTH            SUM(O.TOT_SALES)  
      25. ---------------------------------------- ---------------- ---------------------------------------------------  
      26. Mid-Atlantic                             5月                       1778805  
      27. Mid-Atlantic                             8月                       1381560  
      28. Mid-Atlantic                             9月                       1178694  
      29. Southeast US                             10月                      1610523  
      30. Southeast US                             2月                       1855269  
      31. Southeast US                             3月                       1967979  
      32. Mid-Atlantic                             10月                      1530351  
      33. New England                              8月                       1642968  
      34. New England                              11月                      1384185  
      35. New England                              12月                      1599942  
      36. Southeast US                             11月                      1661598  
      37. Southeast US                             12月                      1841100  
      38. Southeast US                             6月                       1705716  
      39. New England                              7月                       1678002  
      40. Mid-Atlantic                             4月                       1623438  
      41. Mid-Atlantic                             11月                      1598667  
      42. New England                              5月                       1698855  
      43. Southeast US                             8月                       1436295  
      44. New England                              6月                       1510062  
      45. New England                              9月                       1726767  
      46. Southeast US                             4月                       1830051  
      47. Mid-Atlantic                             2月                       1286028  
      48. Mid-Atlantic                             7月                       1820742  
      49. New England                              1月                       1527645  
      50. New England                              3月                       1699449  
      51. New England                              10月                      1648944  
      52. Southeast US                             1月                       1137063  
      53. Southeast US                             5月                       1983282  
      54. Southeast US                             7月                       1670976  
      55. Mid-Atlantic                             1月                       1832091  
      56. Mid-Atlantic                             12月                      1477374  
      57. Southeast US                             9月                       1905633  
      58. Mid-Atlantic                             3月                       1911093  
      59. Mid-Atlantic                             6月                       1504455  
      60. New England                              2月                       1847238  
      61. New England                              4月                       1792866  
      62.           
      63.   
      64.   
      65. 上 面的语句很容易实现对应区域每个月的销售额的汇总统计,但是更复杂的需求,我们可能要对跨越所有月份的每个区域单独汇总,生成小计,并且加上所有区域的汇 总或者对应每个月跨越所有区域,生成小计,并且加上所有月的汇总统计,简而言之,也就是要实现多级别小计和总计的统计。实现这个需求,简单的 group by就无法实现了,下面逐步研究实现的方法。  
      66. 10.1.1 UNION  
      67.         在一个数据仓库应用中,经常需要生成多维度的汇总数据,小计和合计就是跨越多个维度的。生成小计和合计是数据仓库应用的一个核心内容。  
      68.         我们已经意识到,使用简单的group by并不能实现上述汇总查询后,再按照相关列计算小计和合计。那么我们可以使用group by来计算上面我们提到的小计和合计,然后采用union连接相关结果,获得我们想要的答案。  
      69.   
      70. 1.        实现对每个区域按月汇总的数据。  
      71. 2.        实现对每个区域所有月份的小计。  
      72. 3.        实现对所有区域所有月份的总计。  
      73. 分别使用group by实现上述需求,然后union结果。当然这是一种实现方式,在Oracle8i之前,只有这种方式才能实现这种需求,后面我们将要说这种方式的缺点。  
      74. --对每个区域按月分组  
      75. SELECT r.name region,   
      76.        TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month, SUM(o.tot_sales)  
      77. FROM all_orders o JOIN region r  
      78. ON r.region_id = o.region_id  
      79. GROUP BY r.name, o.month  
      80. UNION ALL  
      81. --对每个区域的所有月分组小计,因此,月份为NULL  
      82. SELECT r.name region, NULL, SUM(o.tot_sales)  
      83. FROM all_orders o JOIN region r  
      84. ON r.region_id = o.region_id  
      85. GROUP BY r.name  
      86. UNION ALL  
      87. --对所有区域所有月份总计,因此月份和区域都为NULL  
      88. SELECT NULL, NULL, SUM(o.tot_sales)  
      89. FROM all_orders o JOIN region r  
      90. ON r.region_id = o.region_id;  
      91.   
      92. REGION                               MONTH            SUM(O.TOT_SALES)  
      93. ---------------------------------------- ---------------- ---------------------------------------------------------  
      94. New England                              1月                       1527645  
      95. New England                              2月                       1847238  
      96. New England                              3月                       1699449  
      97. New England                              4月                       1792866  
      98. New England                              5月                       1698855  
      99. New England                              6月                       1510062  
      100. New England                              7月                       1678002  
      101. New England                              8月                       1642968  
      102. New England                              9月                       1726767  
      103. New England                              10月                      1648944  
      104. New England                              11月                      1384185  
      105. New England                              12月                      1599942  
      106. Mid-Atlantic                             1月                       1832091  
      107. Mid-Atlantic                             2月                       1286028  
      108. Mid-Atlantic                             3月                       1911093  
      109.   
      110. Mid-Atlantic                             4月                       1623438  
      111. Mid-Atlantic                             5月                       1778805  
      112. Mid-Atlantic                             6月                       1504455  
      113. Mid-Atlantic                             7月                       1820742  
      114. Mid-Atlantic                             8月                       1381560  
      115. Mid-Atlantic                             9月                       1178694  
      116. Mid-Atlantic                             10月                      1530351  
      117. Mid-Atlantic                             11月                      1598667  
      118. Mid-Atlantic                             12月                      1477374  
      119. Southeast US                             1月                       1137063  
      120. Southeast US                             2月                       1855269  
      121. Southeast US                             3月                       1967979  
      122. Southeast US                             4月                       1830051  
      123. Southeast US                             5月                       1983282  
      124. Southeast US                             6月                       1705716  
      125. Southeast US                             7月                       1670976  
      126. Southeast US                             8月                       1436295  
      127. Southeast US                             9月                       1905633  
      128. Southeast US                             10月                      1610523  
      129. Southeast US                             11月                      1661598  
      130. Southeast US                             12月                      1841100  
      131. Mid-Atlantic                                                      18923298  
      132. New England                                                       19756923  
      133. Southeast US                                                      20605485  
      134.                                                                   59285706          
      135.   
      136. 分析这个结果可以看出,比如Mid_Atlantic的小计数据,就是上面Mid_Atlantic按月分组的明细数据的再次汇总。最后的59285706就是所有按区域和月份分组的明细的汇总,也等于上面按区域汇总的小计的和。  
      137. 其实,现在可以看出,如果有一个分组函数,能够对指定列的全部分组,然后能够对指定列逐渐减少分组,直到所有的列排列完成,比如上面的区域名,月份分组。如果能实现分组统计:  
      138. 区域名,月份  
      139. 区域名                  //对应区域的小计  
      140. 全部汇总                //所有区域所有月份的合计  
      141. 那么我们的问题就能很简单地解决了,Oracle引入了RollUp,专门就是解决这个问题。  
      142.   
      143. 下面回到上面用Union实现这个功能上来,分析它的缺点,首先看下这个查询的执行计划(环境不同,计划可能不同):  
      144. PLAN_TABLE_OUTPUT  
      145.   
      146. -----------------------------------------------------  
      147.   
      148. | Id | Operation                  | Name            |  
      149.   
      150. -----------------------------------------------------  
      151.   
      152. |  0 | SELECT STATEMENT           |                 |  
      153.   
      154. |  1 | UNION-ALL                  |                 |  
      155.   
      156. |  2 | SORT GROUP BY              |                 |  
      157.   
      158. |  3 | MERGE JOIN                 |                 |  
      159.   
      160. |  4 | TABLE ACCESS BY INDEX ROWID| REGION          |  
      161.   
      162. |  5 | INDEX FULL SCAN            | REGION_PK       |  
      163.   
      164. |* 6 | SORT JOIN                  |                 |  
      165.   
      166. |  7 | TABLE ACCESS FULL          | ALL_ORDERS      |  
      167.   
      168. |  8 | SORT GROUP BY              |                 |  
      169.   
      170. |  9 | MERGE JOIN                 |                 |  
      171.   
      172. |  10| TABLE ACCESS BY INDEX ROWID| REGION          |  
      173.   
      174. |  11| INDEX FULL SCAN            | REGION_PK       |  
      175.   
      176. |* 12| SORT JOIN                  |                 |  
      177.   
      178. |  13| TABLE ACCESS FULL          | ALL_ORDERS      |  
      179.   
      180. |  14| SORT AGGREGATE             |                 |  
      181.   
      182. |  15| NESTED LOOPS               |                 |  
      183.   
      184. |  16| TABLE ACCESS FULL          | ALL_ORDERS      |  
      185.   
      186. |* 17| INDEX UNIQUE SCAN          | REGION_PK       |  
      187.   
      188.   
      189.         分析执行计划,得出oracle需要做下列动作才能完成这个查询:  
      190. Three FULL TABLE scans on all_orders  
      191. Three INDEX scan on region_pk (Primary key of table region)  
      192. Two Sort-Merge Joins  
      193. One NESTED LOOPS JOIN  
      194. Two SORT GROUP BY operations  
      195. One SORT AGGREGATE operation  
      196. One UNION ALL  
      197. 可以知道,性能是非常差的,我们的原始表all_orders和region很小,实际上一般最少有几百万条,而且我们的分组汇总列很少,如果很多,还要写更多的union,性能很不好,为了解决这个问题,请看下节ROLLUP。  
      198. 10.1.2 ROLLUP  
      199.         从Oracle8i开始,oracle提供了很多在一个查询中生成多级别汇总数据的特性,第10章我们研究的是对group by的扩展,关于扩展内容和版本对应关系如下表:  
      200.           
      201. 功能        版本  
      202. ROLLUP        oracle8i  
      203. CUBE        oracle8i  
      204. GROUPING SETS        oracle9i  
      205.   
      206.         本节研究rollup,对cube和grouping sets稍后介绍。ROLLUP是对group by的扩展,因此,它只能出现在group by子句中,依赖于分组的列,对每个分组会生成汇总数据,如下:  
      207.         SELECT ….  
      208. FROM ….  
      209. GROUP BY ROLLUP(C1,C2,C3….C(n-1),C(n));  
      210. 总共会进行n+1个分组。  
      211.         那么实际上有n+1个group by的union all结果。  
      212. 1个分组:全分组。C1,C2,C3….C(n-1),C(n)  
      213. 2个分组:C1,C2,C3….C(n-1);//这个分组实际上就是对前面前n-1列分组的小计.  
      214. ----然后逐渐递减分组列  
      215. 第n个分组:C1。对上一个分组的小计。  
      216. 第n+1个分组。不分组全量汇总。相当于合计。也是对group by C1的小计。相当于group by null。  
      217. 有了rollup,对10.1.1实现的union多级别汇总就可以使用rollup实现,如下:  
      218. SELECT r.name region,   
      219. TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month, SUM(o.tot_sales)  
      220. FROM all_orders o JOIN region r  
      221. ON r.region_id = o.region_id  
      222. GROUP BY ROLLUP (r.name, o.month);  
      223. REGION                                   MONTH            SUM(O.TOT_SALES)  
      224. ---------------------------------------- ---------------- ----------------  
      225. New England                              1月                       1527645  
      226. New England                              2月                       1847238  
      227. New England                              3月                       1699449  
      228. New England                              4月                       1792866  
      229. New England                              5月                       1698855  
      230. New England                              6月                       1510062  
      231. New England                              7月                       1678002  
      232. New England                              8月                       1642968  
      233. New England                              9月                       1726767  
      234. New England                              10月                      1648944  
      235. New England                              11月                      1384185  
      236. New England                              12月                      1599942  
      237. New England                                                       19756923  
      238. Mid-Atlantic                             1月                       1832091  
      239. Mid-Atlantic                             2月                       1286028  
      240. Mid-Atlantic                             3月                       1911093  
      241. Mid-Atlantic                             4月                       1623438  
      242. Mid-Atlantic                             5月                       1778805  
      243. Mid-Atlantic                             6月                       1504455  
      244. Mid-Atlantic                             7月                       1820742  
      245. Mid-Atlantic                             8月                       1381560  
      246. Mid-Atlantic                             9月                       1178694  
      247. Mid-Atlantic                             10月                      1530351  
      248. Mid-Atlantic                             11月                      1598667  
      249. Mid-Atlantic                             12月                      1477374  
      250. Mid-Atlantic                                                      18923298  
      251. Southeast US                             1月                       1137063  
      252. Southeast US                             2月                       1855269  
      253. Southeast US                             3月                       1967979  
      254. Southeast US                             4月                       1830051  
      255. Southeast US                             5月                       1983282  
      256. Southeast US                             6月                       1705716  
      257. Southeast US                             7月                       1670976  
      258. Southeast US                             8月                       1436295  
      259. Southeast US                             9月                       1905633  
      260. Southeast US                             10月                      1610523  
      261. Southeast US                             11月                      1661598  
      262. Southeast US                             12月                      1841100  
      263. Southeast US                                                      20605485  
      264.                                                                   59285706  
      265.   
      266. 从 上面的结果可以看出,rollup和group by联合一起使用,达到了按group by列顺序分组,并且实现小计和合计的功能。黄色部分就是对上面 组的小计,最后红色的就是合计。而且,rollup这种分组还是有序的,先全部分组,然后对每个分组小计,最后合计,使处理结果更清楚。 union all就很难实现这种效果了。而且最重要的是性能比union all好,通过上面查询的执行计划可以看出:  
      267.            
      268. rollup仅仅一个索引扫描region,一个全表扫描all_orders,然后通过nested loop,最后sort group by rollup就能得到结果。比union all多次扫描效率高很多。  
      269.   
      270. rollup改变列的顺序,可以轻松改变统计结果,上面的查询小计是对每个区域的所有月小计,我们可以改变列的顺序达到对每个月份的所有区域小计,如下:  
      271. SELECT r.name region,   
      272.        TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month, SUM(o.tot_sales)  
      273. FROM all_orders o JOIN region r  
      274. ON r.region_id = o.region_id  
      275. GROUP BY ROLLUP ( o.month,r.name);  
      276. REGION                                MONTH            SUM(O.TOT_SALES)  
      277. ---------------------------------------- ---------------- ----------------  
      278. New England                             1月                       1527645  
      279. Mid-Atlantic                             1月                       1832091  
      280. Southeast US                             1月                       1137063  
      281.                                         1月                       4496799  
      282. New England                             2月                       1847238  
      283. Mid-Atlantic                              2月                       1286028  
      284. Southeast US                              2月                       1855269  
      285.                                          2月                       4988535  
      286. New England                              3月                       1699449  
      287. Mid-Atlantic                             3月                       1911093  
      288. Southeast US                             3月                       1967979  
      289.                                          3月                       5578521  
      290. New England                              4月                       1792866  
      291. Mid-Atlantic                             4月                       1623438  
      292. Southeast US                             4月                       1830051  
      293.                                          4月                       5246355  
      294. New England                              5月                       1698855  
      295. Mid-Atlantic                             5月                       1778805  
      296. Southeast US                             5月                       1983282  
      297.                                          5月                       5460942  
      298. New England                              6月                       1510062  
      299. Mid-Atlantic                             6月                       1504455  
      300. Southeast US                             6月                       1705716  
      301.                                          6月                       4720233  
      302. New England                              7月                       1678002  
      303. Mid-Atlantic                             7月                       1820742  
      304. Southeast US                             7月                       1670976  
      305.                                          7月                       5169720  
      306. New England                              8月                       1642968  
      307. Mid-Atlantic                             8月                       1381560  
      308. Southeast US                             8月                       1436295  
      309.                                          8月                       4460823  
      310. New England                              9月                       1726767  
      311. Mid-Atlantic                             9月                       1178694  
      312. Southeast US                             9月                       1905633  
      313.                                          9月                       4811094  
      314. New England                              10月                      1648944  
      315. Mid-Atlantic                             10月                      1530351  
      316. Southeast US                             10月                      1610523  
      317.                                          10月                      4789818  
      318. New England                              11月                      1384185  
      319. Mid-Atlantic                             11月                      1598667  
      320. Southeast US                             11月                      1661598  
      321.                                          11月                      4644450  
      322. New England                              12月                      1599942  
      323. Mid-Atlantic                             12月                      1477374  
      324. Southeast US                             12月                      1841100  
      325.                                          12月                      4918416  
      326.                                                                   59285706  
      327. 可以看出,达到了按月小计的功能,当然最后红色的合计值和按区域小计一致。  
      328. 注意:  
      329. rollup中列的顺序不同,则统计的结果不同。因为它是按列从右递减分组的。  
      330. 比如,我们需要统计第1个季度,并且年月汇总所有区域的数据,如下:  
      331. SELECT o.year, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,  
      332. r.name region, SUM(o.tot_sales) sums  
      333. FROM all_orders o JOIN region r  
      334. ON r.region_id = o.region_id  
      335. WHERE o.month BETWEEN 1 AND 3  
      336. GROUP BY ROLLUP (o.year, o.month, r.name);  
      337.   
      338. YEAR MONTH         REGION                                         SUMS  
      339. --------- ---------------- ---------------------------------------- ---------------------------------------------  
      340.      2000 1月              New England                                 1018430  
      341.      2000 1月              Mid-Atlantic                                1221394  
      342.      2000 1月              Southeast US                                 758042  
      343.      2000 1月                                                          2997866  
      344.      2000 2月              New England                                 1231492  
      345.      2000 2月              Mid-Atlantic                                 857352  
      346.      2000 2月              Southeast US                                1236846  
      347.      2000 2月                                                          3325690  
      348.      2000 3月              New England                                 1132966  
      349.      2000 3月              Mid-Atlantic                                1274062  
      350.      2000 3月              Southeast US                                1311986  
      351.      2000 3月                                                          3719014  
      352.      2000                                                             10042570  
      353.      2001 1月              New England                                  509215  
      354.      2001 1月              Mid-Atlantic                                 610697  
      355.      2001 1月              Southeast US                                 379021  
      356.      2001 1月                                                          1498933  
      357.      2001 2月              New England                                  615746  
      358.      2001 2月              Mid-Atlantic                                 428676  
      359.      2001 2月              Southeast US                                 618423  
      360.      2001 2月                                                          1662845  
      361.      2001 3月              New England                                  566483  
      362.      2001 3月              Mid-Atlantic                                 637031  
      363.      2001 3月              Southeast US                                 655993  
      364.      2001 3月                                                          1859507  
      365.      2001                                                              5021285  
      366.                                                                       15063855  
      367. 可以看出,只要在rollup中增加或改变相关列的顺序,就能达到我们想要的小计和合计功能。  
      368. 10.1.3部分ROLLUP  
      369. 以上使用的rollup是完全的rollup查询,比如有n列,那么会生成n-1个小计,然后n-2个小计对n-1个,直到汇总合计。如果在实际查询中,有的小计或合计我们不需要,那么久要使用局部rollup,局部rollup就是将不需要小计(合计)的列放在group by中,而不是放在rollup中。  
      370. 请看下面的查询:  
      371. SELECT o.year, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,  
      372. r.name region, SUM(o.tot_sales)  
      373. FROM all_orders o JOIN region r  
      374. ON r.region_id = o.region_id  
      375. WHERE o.month BETWEEN 1 AND 3  
      376. GROUP BY o.year, ROLLUP (o.month, r.name);  
      377. 这个相当于GROUP BY ROLLUP (o.year,o.month, r.name) 但是去掉了最后一行的汇总。  
      378. 因为每次分组都有year。没有group by null。  
      379. 再看这个查询:  
      380. SELECT o.year, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,  
      381. r.name region, SUM(o.tot_sales)  
      382. FROM all_orders o JOIN region r  
      383. ON r.region_id = o.region_id  
      384. WHERE o.month BETWEEN 1 AND 3  
      385. GROUP BY o.year, o.month,ROLLUP (r.name);  
      386. 这个相当于GROUP BY ROLLUP (o.year,o.month, r.name)去掉了对指定年的汇总和全量汇总。因为每次都有对year和month的分组,小计只有对年和月的小计,如下:  
      387.   
      388.       YEAR MONTH        REGION                            SUM(o.tot_sales)  
      389. ---------- ---------------- ---------------------------------------- ----------------------------------------------  
      390.       2000 1月              New England                                 1018430  
      391.       2000 1月              Mid-Atlantic                                1221394  
      392.       2000 1月              Southeast US                                 758042  
      393.       2000 1月                                                          2997866  
      394.       2000 2月              New England                                 1231492  
      395.       2000 2月              Mid-Atlantic                                 857352  
      396.       2000 2月              Southeast US                                1236846  
      397.       2000 2月                                                          3325690  
      398.       2000 3月              New England                                 1132966  
      399.       2000 3月              Mid-Atlantic                                1274062  
      400.       2000 3月              Southeast US                                1311986  
      401.       2000 3月                                                          3719014  
      402.       2001 1月              New England                                  509215  
      403.       2001 1月              Mid-Atlantic                                 610697  
      404.       2001 1月              Southeast US                                 379021  
      405.       2001 1月                                                          1498933  
      406.       2001 2月              New England                                  615746  
      407.       2001 2月              Mid-Atlantic                                 428676  
      408.       2001 2月              Southeast US                                 618423  
      409.       2001 2月                                                          1662845  
      410.       2001 3月              New England                                  566483  
      411.       2001 3月              Mid-Atlantic                                 637031  
      412.       2001 3月              Southeast US                                 655993  
      413.       2001 3月                                                          1859507  
      414.   
      415.   
      416.   
      417. 10.1.4 CUBE  
      418. CUBE(交 叉列表)也是对group by运算的一种扩展,它比rollup扩展更加精细,组合类型更多,rollup是按组合的列从右到左递减分组计算,而 CUBE则是对所有可能的组合情况进行分组,这样分组的情况更多,覆盖所有的可能分组,并计算所有可能的分组的小计。比如:  
      419. CUBE(C1,C2,C3……C(N))对N个列进行CUBE分组,那么可能的分组情况有:  
      420. 不分组:C(n,0)  
      421. 取一列分组:C(n,1)  
      422. -----  
      423. 取N列分组,全分组:C(n,n)  
      424. 那么运用数学上的组合公式,得出所有所有可能的组合方式有:C(n,0)+C(n,1)+….+C(n,n)=2^n种。  
      425. 我们以前面的rollup组合列为例子:rollup(name,month)是计算按区域名和月份分组以及每个区域的所有月份的小计以及总计。但是使用cube(name,month)则有4种分组,比rollup多一个每个月的所有区域的小计。下面比较一下这两种分组方式:  
      426.   
      427. 分组公式        描述  
      428. rollup(name,month)        分组情况有:  
      429. group by name,month  
      430. group by name,null  //每个区域所有月份小计  
      431. group by null,null  //合计  
      432. cube(name,month)        分组情况有:  
      433. group by null,null  //总计  
      434. group by null,month //每个月份的所有区域小计  
      435. group by name,null //每个区域的所有月份小计  
      436. group by name,month  
      437.         
      438. CUBE使用方式:  
      439. 和rollup一样,是  
      440. select …  
      441. from …  
      442. group by cube(分组列列表)  
      443. 请看上面表格中的分组例子:  
      444. SELECT r.name region, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,   
      445. SUM(o.tot_sales) sums  
      446. FROM all_orders o JOIN region r  
      447. ON r.region_id = o.region_id  
      448. GROUP BY CUBE(r.name, o.month)  
      449.   
      450. REGION                                   MONTH                  SUMS  
      451. ---------------------------------------- ---------------- ---------------------------------------------------  
      452.                                                             59285706  
      453.                                          1月                 4496799  
      454.                                          2月                 4988535  
      455.                                          3月                 5578521  
      456.                                          4月                 5246355  
      457.                                          5月                 5460942  
      458.                                          6月                 4720233  
      459.                                          7月                 5169720  
      460.                                          8月                 4460823  
      461.                                          9月                 4811094  
      462.                                          10月                4789818  
      463.                                          11月                4644450  
      464.                                          12月                4918416  
      465. New England                                                 19756923  
      466. New England                              1月                 1527645  
      467. New England                              2月                 1847238  
      468. New England                              3月                 1699449  
      469. New England                              4月                 1792866  
      470. New England                              5月                 1698855  
      471. New England                              6月                 1510062  
      472. New England                              7月                 1678002  
      473. New England                              8月                 1642968  
      474. New England                              9月                 1726767  
      475. New England                              10月                1648944  
      476. New England                              11月                1384185  
      477. New England                              12月                1599942  
      478. Mid-Atlantic                                                18923298  
      479. Mid-Atlantic                             1月                 1832091  
      480. Mid-Atlantic                             2月                 1286028  
      481. Mid-Atlantic                             3月                 1911093  
      482. Mid-Atlantic                             4月                 1623438  
      483. Mid-Atlantic                             5月                 1778805  
      484. Mid-Atlantic                             6月                 1504455  
      485. Mid-Atlantic                             7月                 1820742  
      486. Mid-Atlantic                             8月                 1381560  
      487. Mid-Atlantic                             9月                 1178694  
      488. Mid-Atlantic                             10月                1530351  
      489. Mid-Atlantic                             11月                1598667  
      490. Mid-Atlantic                             12月                1477374  
      491. Southeast US                                                20605485  
      492. Southeast US                             1月                 1137063  
      493. Southeast US                             2月                 1855269  
      494. Southeast US                             3月                 1967979  
      495. Southeast US                             4月                 1830051  
      496. Southeast US                             5月                 1983282  
      497. Southeast US                             6月                 1705716  
      498. Southeast US                             7月                 1670976  
      499. Southeast US                             8月                 1436295  
      500. Southeast US                             9月                 1905633  
      501. Southeast US                             10月                1610523  
      502. Southeast US                             11月                1661598  
      503. Southeast US                             12月                1841100  
      504.   
      505. 从上面结果可以看出,红色部分为group by null,null的结果,计算合计值。黄色部分为group by null,month的结果,计算每个月中所有区域的小计。绿色为group by name,null的结果,计算每个区域所有月份的小计。灰色的为group by name,month的结果。其中:  
      506. group by name,month的所有结果的和=group by name,null的和=group by null,month的和=合计值。  
      507. group by name,month中对应name的和=group by name,null对应的name的值。  
      508. group by name,month中对应month的和=group by null,month对应month的和。  
      509.   
      510.   
      511. 当然对于cube的运算,和rollup一样,也可以使用union实现,但是cube的组合方式呈级数增长,则union也会增长,而且性能不好,访问表多次,无cube的优化,语句没有cube简单。上例我们可以使用对应的4个group by 然后union all获得结果,但是结果的顺序不能保证。  
      512. SELECT NULL region, NULL month, SUM(o.tot_sales)  
      513. FROM all_orders o JOIN region r  
      514. ON r.region_id = o.region_id   
      515. UNION ALL  
      516. SELECT NULL, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month, SUM(o.tot_sales)  
      517. FROM all_orders o JOIN region r  
      518. ON r.region_id = o.region_id  
      519. GROUP BY o.month  
      520. UNION ALL  
      521. SELECT r.name region, NULL, SUM(o.tot_sales)  
      522. FROM all_orders o JOIN region r  
      523. ON r.region_id = o.region_id  
      524. GROUP BY r.name  
      525. UNION ALL  
      526. SELECT r.name region, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,   
      527. SUM(o.tot_sales)  
      528. FROM all_orders o JOIN region r  
      529. ON r.region_id = o.region_id  
      530. GROUP BY r.name, o.month;  
      531.   
      532. 看下union的执行计划:  
      533. 只需要访问region和all_orders一次,而且有专门的GENERATE CUBE计算,提高效率,保证执行结果的有序性。  
      534. 实际上,有上面对cube的分析可以得出,那个cube语句实际上等价于下列rollup语句:  
      535. SELECT r.name region, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,   
      536. SUM(o.tot_sales)  
      537. FROM all_orders o JOIN region r  
      538. ON r.region_id = o.region_id  
      539. GROUP BY rollup(r.name, o.month)  
      540. union   
      541. SELECT r.name region, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,   
      542. SUM(o.tot_sales)  
      543. FROM all_orders o JOIN region r  
      544. ON r.region_id = o.region_id  
      545. GROUP BY rollup( o.month,r.name);  
      546. 不可以使用union all,因为有重复数据。  
      547.   
      548.   
      549. 对于CUBE来说,列的名字只要一样,那么顺序无所谓,结果都是一样的,因为cube是各种可能情况的组合,只不过统计的结果顺序不同而已。但是对于rollup来说,列的顺序不同,则结果不同,详细见rollup。  
      550.   
      551.         对本章的cube例子,改写cube的顺序,如下:  
      552. SELECT r.name region, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,   
      553. SUM(o.tot_sales) sums  
      554. FROM all_orders o JOIN region r  
      555. ON r.region_id = o.region_id  
      556. GROUP BY CUBE(o.month, r.name);  
      557. REGION                                   MONTH                  SUMS  
      558. ---------------------------------------- ---------------- ----------------------------------------------------  
      559.                                                             59285706  
      560. New England                                                 19756923  
      561. Mid-Atlantic                                                18923298  
      562. Southeast US                                                20605485  
      563.                                          1月                 4496799  
      564. New England                              1月                 1527645  
      565. Mid-Atlantic                             1月                 1832091  
      566. Southeast US                             1月                 1137063  
      567.                                          2月                 4988535  
      568. New England                              2月                 1847238  
      569. Mid-Atlantic                             2月                 1286028  
      570. Southeast US                             2月                 1855269  
      571.                                          3月                 5578521  
      572. New England                              3月                 1699449  
      573. Mid-Atlantic                             3月                 1911093  
      574. Southeast US                             3月                 1967979  
      575.                                          4月                 5246355  
      576. New England                              4月                 1792866  
      577. Mid-Atlantic                             4月                 1623438  
      578. Southeast US                             4月                 1830051  
      579.                                          5月                 5460942  
      580. New England                              5月                 1698855  
      581. Mid-Atlantic                             5月                 1778805  
      582. Southeast US                             5月                 1983282  
      583.                                          6月                 4720233  
      584. New England                              6月                 1510062  
      585. Mid-Atlantic                             6月                 1504455  
      586. Southeast US                             6月                 1705716  
      587.                                          7月                 5169720  
      588. New England                              7月                 1678002  
      589. Mid-Atlantic                             7月                 1820742  
      590. Southeast US                             7月                 1670976  
      591.                                          8月                 4460823  
      592. New England                              8月                 1642968  
      593. Mid-Atlantic                             8月                 1381560  
      594. Southeast US                             8月                 1436295  
      595.                                          9月                 4811094  
      596. New England                              9月                 1726767  
      597. Mid-Atlantic                             9月                 1178694  
      598. Southeast US                             9月                 1905633  
      599.                                          10月                4789818  
      600. New England                              10月                1648944  
      601. Mid-Atlantic                             10月                1530351  
      602. Southeast US                             10月                1610523  
      603.                                          11月                4644450  
      604. New England                              11月                1384185  
      605. Mid-Atlantic                             11月                1598667  
      606. Southeast US                             11月                1661598  
      607.                                          12月                4918416  
      608. New England                              12月                1599942  
      609. Mid-Atlantic                             12月                1477374  
      610. Southeast US                             12月                1841100  
      611.           
      612. 我们可以看出,与cube(r.name,o.month)结果一样,只不过顺序不一样。cube(o.month,r.name)的顺序是:  
      613. group by null,null  
      614. group by null,r.name  
      615. group by o.month,null  
      616. group by o.month,r.name  
      617. 其中最后两个分组是先小计再分组。  
      618.   
      619. 10.1.5部分CUBE  
      620.  部分CUBE和部分ROLLUP类似,把不想要的小计和合计的列放到group by中,不放到cube中就可以了。比如:  
      621. SELECT r.name region, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,   
      622. SUM(o.tot_sales) sums  
      623. FROM all_orders o JOIN region r  
      624. ON r.region_id = o.region_id  
      625. GROUP BY r.name, CUBE(o.month);  
      626. REGION                                   MONTH                  SUMS  
      627. ---------------------------------------- ---------------- -------------------------------------------------  
      628. New England                                                 19756923  
      629. New England                              1月                 1527645  
      630. New England                              2月                 1847238  
      631. New England                              3月                 1699449  
      632. New England                              4月                 1792866  
      633. New England                              5月                 1698855  
      634. New England                              6月                 1510062  
      635. New England                              7月                 1678002  
      636. New England                              8月                 1642968  
      637. New England                              9月                 1726767  
      638. New England                              10月                1648944  
      639. New England                              11月                1384185  
      640. New England                              12月                1599942  
      641. Mid-Atlantic                                                18923298  
      642. Mid-Atlantic                             1月                 1832091  
      643. Mid-Atlantic                             2月                 1286028  
      644. Mid-Atlantic                             3月                 1911093  
      645. Mid-Atlantic                             4月                 1623438  
      646. Mid-Atlantic                             5月                 1778805  
      647. Mid-Atlantic                             6月                 1504455  
      648. Mid-Atlantic                             7月                 1820742  
      649. Mid-Atlantic                             8月                 1381560  
      650. Mid-Atlantic                             9月                 1178694  
      651. Mid-Atlantic                             10月                1530351  
      652. Mid-Atlantic                             11月                1598667  
      653. Mid-Atlantic                             12月                1477374  
      654. Southeast US                                                20605485  
      655. Southeast US                             1月                 1137063  
      656. Southeast US                             2月                 1855269  
      657. Southeast US                             3月                 1967979  
      658. Southeast US                             4月                 1830051  
      659. Southeast US                             5月                 1983282  
      660. Southeast US                             6月                 1705716  
      661. Southeast US                             7月                 1670976  
      662. Southeast US                             8月                 1436295  
      663. Southeast US                             9月                 1905633  
      664. Southeast US                             10月                1610523  
      665. Southeast US                             11月                1661598  
      666. Southeast US                             12月                1841100  
      667.    
      668. 从上面结果可以看出,当将区域名从cube中移到group by中,则总会按区域名统计,则结果中移除了按月小计和总计的结果。我们可以发现,如果cube中只有一个列,那么和rollup的结果一致,也就是上面的语句等价于:  
      669. SELECT r.name region, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,   
      670. SUM(o.tot_sales) sums  
      671. FROM all_orders o JOIN region r  
      672. ON r.region_id = o.region_id  
      673. GROUP BY r.name, rollup(o.month);  
      674.   
      675. 注:对上面的rollup和cube的小计或总计中,有的列是null的表示按此列小计,如果前面的非汇总列都是null则表示总计。在实际应用中不可能把这些null给别人看,因为别人不知道你是用rollup或cube计算的。这时候可能会用到nvl或其它的转换,详细请看下节grouing函数。  
      676.   
      677. 10.1.6 GROUPING函数  
      678.  在实际应用中,使用rollup或cube可以统计小计和合计的值,那么在小计和合计中会出现列的值为NULL的情况,客户就不知道什么意思了。为了增强客户的可读性,我们可能会想到使用NVL函数,如下:  
      679. SELECT NVL(TO_CHAR(o.year), 'All Years') year,  
      680. NVL(TO_CHAR(TO_DATE(o.month, 'MM'), 'Month'), 'First Quarter') month,  
      681. NVL(r.name, 'All Regions') region, SUM(o.tot_sales) sums  
      682. FROM all_orders o JOIN region r  
      683. ON r.region_id = o.region_id  
      684. WHERE o.month BETWEEN 1 AND 3  
      685. GROUP BY ROLLUP (o.year, o.month, r.name);  
      686. YEAR       MONTH                REGION                     SUMS  
      687. ---------- -------------------- -------------------- -----------------------------------------------------  
      688. 2000       1月                  New England             1018430  
      689. 2000       1月                  Mid-Atlantic            1221394  
      690. 2000       1月                  Southeast US             758042  
      691. 2000       1月                  All Regions             2997866  
      692. 2000       2月                  New England             1231492  
      693. 2000       2月                  Mid-Atlantic             857352  
      694. 2000       2月                  Southeast US            1236846  
      695. 2000       2月                  All Regions             3325690  
      696. 2000       3月                  New England             1132966  
      697. 2000       3月                  Mid-Atlantic            1274062  
      698. 2000       3月                  Southeast US            1311986  
      699. 2000       3月                  All Regions             3719014  
      700. 2000       First Quarter        All Regions            10042570  
      701. 2001       1月                  New England              509215  
      702. 2001       1月                  Mid-Atlantic             610697  
      703. 2001       1月                  Southeast US             379021  
      704. 2001       1月                  All Regions             1498933  
      705. 2001       2月                  New England              615746  
      706. 2001       2月                  Mid-Atlantic             428676  
      707. 2001       2月                  Southeast US             618423  
      708. 2001       2月                  All Regions             1662845  
      709. 2001       3月                  New England              566483  
      710. 2001       3月                  Mid-Atlantic             637031  
      711. 2001       3月                  Southeast US             655993  
      712. 2001       3月                  All Regions             1859507  
      713. 2001       First Quarter        All Regions             5021285  
      714. All Years  First Quarter        All Regions            15063855  
      715.   
      716. 可 以看出,原来是NULL的都被有意义的值代替,增加了用户可读性。使用NVL函数对这个例子来说是非常适合的,但是另外一个情况我们要考虑一下,如果这些 列中本身就有NULL值的存在,那么我们使用NVL函数之后,到底是小计还是本身的值呢???带着这个问题,我们来看一个例子:  
      717. SELECT * FROM disputed_orders;  
      718. ORDER_NBR CUST_NBR SALES_EMP_ID SALE_PRICE ORDER_DT    EXPECTED_SHIP_DT  STATUS  
      719. --------- -------- ------------ ---------- ----------- -------------- ---------  
      720.      1001        1         7354         99 22-jul-2001 23-jul-2001    DELIVERED  
      721.      1000        1         7354            19-jul-2001 24-jul-2001  
      722.      1002        5         7368            12-jul-2001 25-jul-2001  
      723.      1003        4         7654         56 16-jul-2001 26-jul-2001    DELIVERED  
      724.      1004        4         7654         34 18-jul-2001 27-jul-2001    PENDING  
      725.      1005        8         7654         99 22-jul-2001 24-jul-2001    DELIVERED  
      726.      1006        1         7354            22-jul-2001 28-jul-2001  
      727.      1007        5         7368         25 20-jul-2001 22-jul-2001    PENDING  
      728.      1008        5         7368         25 21-jul-2001 23-jul-2001    PENDING  
      729.      1009        1         7354         56 18-jul-2001 22-jul-2001    DELIVERED  
      730.      1012        1         7354         99 22-jul-2001 23-jul-2001    DELIVERED  
      731.      1011        1         7354            19-jul-2001 24-jul-2001  
      732.      1015        5         7368            12-jul-2001 25-jul-2001  
      733.      1017        4         7654         56 16-jul-2001 26-jul-2001    DELIVERED  
      734.      1019        4         7654         34 18-jul-2001 27-jul-2001    PENDING  
      735.      1021        8         7654         99 22-jul-2001 24-jul-2001    DELIVERED  
      736.      1023        1         7354            22-jul-2001 28-jul-2001  
      737.      1025        5         7368         25 20-jul-2001 22-jul-2001    PENDING  
      738.      1027        5         7368         25 21-jul-2001 23-jul-2001    PENDING  
      739.      1029        1         7354         56 18-jul-2001 22-jul-2001    DELIVERED  
      740.    
      741. 可以看到,有的status值为NULL。那么现在我们需要汇总每个customer对应状态的数目以及所有customer每个状态的数目最后合计。使用NVL函数如下:  
      742. SELECT NVL(TO_CHAR(cust_nbr), 'All Customers') customer,   
      743. NVL(status, 'All Status') status,  
      744. COUNT(*) FROM disputed_orders  
      745. GROUP BY CUBE(cust_nbr, status);  
      746. CUSTOMER             STATUS                 COUNT(*)  
      747. -------------------- -------------------- ----------  
      748. All Customers        All Status                    6  
      749. All Customers        All Status                   20  
      750. All Customers        PENDING                       6  
      751. All Customers        DELIVERED                     8  
      752. 1                    All Status                    4  
      753. 1                    All Status                    8  
      754. 1                    DELIVERED                     4  
      755. 4                    All Status                    4  
      756. 4                    PENDING                       2  
      757. 4                    DELIVERED                     2  
      758. 5                    All Status                    2  
      759. 5                    All Status                    6  
      760. 5                    PENDING                       4  
      761. 8                    All Status                    2  
      762. 8                    DELIVERED                     2  
      763.   
      764. 从上面的结果可以看出,这种使用NVL函数没有任何意义,得出的结果混淆,比如黄色部分,对用户1有两个all status,其实其中一个是本身表中的status为null,因此统计混乱。  
      765.         Oracle为了解决这个问题,专门有一个grouping函数。grouping函数解释如下:  
      766. 1.        grouping函数只有一个参数,接受来自于group by,rollup,cube,grouping sets的列。  
      767. 2.        grouping函数对rollup,cube的汇总列(小计或合计行的列值)置为1,其他的非汇总列置为0,如在单独的group by中使用肯定全为0,因为没有通过rollup或cube的小计或合计行。  
      768. 3.        grouping函数可以有效地避免nvl函数带来的小计或合计与本身表中有null带来的混淆问题。  
      769. 4.        使用方式为:  
      770. SELECT  . . .  [GROUPING(grouping_column_name)]  . . .   
      771. FROM  . . .   
      772. GROUP BY  . . .  {ROLLUP | CUBE} (grouping_column_name)  
      773. 下面用grouping函数改写上面的的例子如下:  
      774. SELECT  decode(grouping(cust_nbr),1,'ALL CUSTOMER',cust_nbr) customer,   
      775. decode(grouping(status),1,'ALL STATUS',nvl(status,'原始值为空')) status,  
      776. COUNT(*) FROM disputed_orders  
      777. GROUP BY CUBE(cust_nbr, status);  
      778. CUSTOMER             STATUS                 COUNT(*)  
      779. -------------------- -------------------- ----------  
      780. ALL CUSTOMER         原始值为空                    6  
      781. ALL CUSTOMER         ALL STATUS                   20  
      782. ALL CUSTOMER         PENDING                       6  
      783. ALL CUSTOMER         DELIVERED                     8  
      784. 1                    原始值为空                    4  
      785. 1                    ALL STATUS                    8  
      786. 1                    DELIVERED                     4  
      787. 4                    ALL STATUS                    4  
      788. 4                    PENDING                       2  
      789. 4                    DELIVERED                     2  
      790. 5                    原始值为空                    2  
      791. 5                    ALL STATUS                    6  
      792. 5                    PENDING                       4  
      793. 8                    ALL STATUS                    2  
      794. 8                    DELIVERED                     2                  
      795. 使用decode和grouping函数,避免了null的问题,现在黄色部分对status为null的也统计了。汇总和status为null的不再混淆。  
      796.   
      797. 再看一个例子:  
      798. SELECT DECODE(GROUPING(o.year), 1, 'All Years', o.year) Year,  
      799. DECODE(GROUPING(o.month), 1, 'All Months',   
      800. TO_CHAR(TO_DATE(o.month, 'MM'), 'Month')) Month,  
      801. DECODE(GROUPING(r.name), 1, 'All Regions', r.name) Region, SUM(o.tot_sales) sums  
      802. FROM all_orders o JOIN region r  
      803. ON r.region_id = o.region_id  
      804. WHERE o.month BETWEEN 1 AND 3  
      805. GROUP BY ROLLUP (o.year, o.month, r.name);  
      806. YEAR       MONTH                REGION                     SUMS  
      807. ---------- -------------------- -------------------- ----------  
      808. 2000       January              New England             1018430  
      809. 2000       January              Mid-Atlantic            1221394  
      810. 2000       January              Southeast US             758042  
      811. 2000       January              All Regions             2997866  
      812. 2000       February             New England             1231492  
      813. 2000       February             Mid-Atlantic             857352  
      814. 2000       February             Southeast US            1236846  
      815. 2000       February             All Regions             3325690  
      816. 2000       March                New England             1132966  
      817. 2000       March                Mid-Atlantic            1274062  
      818. 2000       March                Southeast US            1311986  
      819. 2000       March                All Regions             3719014  
      820. 2000       All Months           All Regions            10042570  
      821. 2001       January              New England              509215  
      822. 2001       January              Mid-Atlantic             610697  
      823. 2001       January              Southeast US             379021  
      824. 2001       January              All Regions             1498933  
      825. 2001       February             New England              615746  
      826. 2001       February             Mid-Atlantic             428676  
      827. 2001       February             Southeast US             618423  
      828. 2001       February             All Regions             1662845  
      829. 2001       March                New England              566483  
      830. 2001       March                Mid-Atlantic             637031  
      831. 2001       March                Southeast US             655993  
      832. 2001       March                All Regions             1859507  
      833. 2001       All Months           All Regions             5021285  
      834. All Years  All Months           All Regions            15063855  
      835.   
      836. 使用deocode(当然也可以用case,没有decode简单)联合grouping函数,使报表的小计和合计列描述有意义,避免原始数据有null而使用nvl函数带来混淆的问题。  
      837.   
      838. 10.1.6 GROUPING SETS  
      839.   
      840. 以 上我们已经掌握了rollup,cube分组统计的知识。但是rollup和cube的分组统计包含了常规group by的统计明细以及对相关列的小计 和合计值。如果我们需要的只是按每个分组列小计呢?oracle提供了grouping sets操作,对group by的另一个扩展,专门对分组列分 别进行小计计算,不包括合计。使用方式和rollup和cube一样,都是放在group by中。如:  
      841. grouping sets(C1,C2….Cn)则分组方式有n种,等于列的数目。  
      842. group by c1,null,null…..null。  
      843. group by null,c2,null….null。  
      844. ….  
      845. group by null,null……..Cn。  
      846. 无group by null,null….null,也就是说没有合计行。  
      847. 注意:grouping sets的统计结果和列的顺序无关。  
      848. 如下例:  
      849. SELECT o.year, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,  
      850. r.name region, SUM(o.tot_sales) sums  
      851. FROM all_orders o JOIN region r  
      852. ON r.region_id = o.region_id  
      853. WHERE o.month BETWEEN 1 AND 3  
      854. GROUP BY GROUPING SETS (o.year, o.month, r.name);  
      855.            
      856. YEAR MONTH                REGION                     SUMS  
      857. ----- -------------------- -------------------- ------------------------------------------------  
      858.                            New England             5074332  
      859.                            Mid-Atlantic            5029212  
      860.                            Southeast US            4960311  
      861.       January                                      4496799  
      862.       February                                     4988535  
      863.       March                                        5578521  
      864. 2001                                              5021285  
      865. 2000                                             10042570  
      866.           
      867. 可以看出,没有常规group by统计结果,只有按每个单独列的小计,也不包含合计。改变grouping sets中列的顺序,不影响结果,上面的语句等价于:  
      868. SELECT o.year, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,  
      869. r.name region, SUM(o.tot_sales) sums  
      870. FROM all_orders o JOIN region r  
      871. ON r.region_id = o.region_id  
      872. WHERE o.month BETWEEN 1 AND 3  
      873. GROUP BY GROUPING SETS (o.month, r.name, o.year);  
      874.   
      875. 10.1.7ROLLUP、CUBE、GROUPING SETS总结  
      876. 本章已经学习了小计和合计的三个主要增强的group by操作:rollup,cube,grouping sets操作。下面总结下他们的使用以及区别。  
      877.           
      878. 操作名        简述        列顺序是否要求        分组情况        使用情况  
      879. ROLLUP        ROLLUP操作可以查询出常规group by的结果以及按列小计和合计的结果。        和列顺序有关。见分组情况。        ROLLUP(C1,C2…Cn)。  
      880. 总共会进行n+1个分组。那么实际上有n+1个group by的union all结果。  
      881. 顺序为:  
      882. group by C1,C2….Cn  
      883. group by C1,C2,….Cn-1  
      884. group by C1,C2….Cn-2  
      885. group by C1  
      886. group by null,….null  
      887. 可以看出是从右到左逐渐递减列的group by,所以和列的顺序有关,顺序不同,意义不同。  
      888. 需要查询的分组明细以及小计和合计功能的时候使用。  
      889. CUBE        CUBE操作是对所有可能的列组合分组,包括常规group by以及所有分组小计和合计的值。        和列顺序无关。        CUBE(C1,C2,C3……C(N))对N个列进行CUBE分组,那么可能的分组情况有:  
      890. 不分组:C(n,0)  
      891. 取一列分组:C(n,1)  
      892. 取N列分组,全分组:C(n,n)  
      893. 那么运用数学上的组合公式,得出所有所有可能的组合方式有:C(n,0)+C(n,1)+….+C(n,n)=2^n种。  
      894. 如果只有一个列,那么和rollup一样。  
      895. 比如cube(name,month)  
      896. 分组情况有:  
      897. group by null,null  //总计C(2,0)  
      898. group by null,month //每个月份的所有区域小计  
      899. group by name,null //每个区域的所有月份小计 C(2,1)  
      900. group by name,month //C(2,2)常规group by  
      901. 因此,结果和列的顺序无关。  
      902. 适用于需要统计各种可能的组合情况的小计和合计以及常规分组明细。  
      903. GROUPING SETS        只查询按每个列小计的结果,不包含合计值        和列顺序无关。        分组种类=列的数目。  
      904. grouping sets(C1,C2,…Cn)  
      905. 那么等价于下列union all  
      906. group by C1,null…..  
      907. group by null,C2….  
      908. …  
      909. group by null,null….Cn        适用于只需要按每个列小计。  
      910.   
      911. 10.2分组扩展功能增强  
      912.         10.1节我们只是对分组扩展功能使用了几个简单的例子说明,还足以证明扩展分组功能的强大,这些简单的例子适用于oracle8i以及后续版本,但是在Oracle9i开始,对分组扩展的功能提供了新的可行操作:  
      913.         ◆ 在group by子句中可以重复列名。  
      914.         ◆ 对复合列进行分组。  
      915. ◆ 分组连接。  
      916. 本节内容就是围绕上面3点在9i中引入的分组扩展扩展新功能展开。  
      917.   
      918. 10.2.1在group by中使用重复列在Oracle8i的时候,在group by中重复列名是不允许的。比如group by中包含了扩展子句(cube,rollup等),在这些扩展子句内外使用相同的列名是不合法的,比如在oracle8i中这样写:  
      919. SELECT o.year, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,  
      920. r.name region, SUM(o.tot_sales) total  
      921. FROM all_orders o JOIN region r  
      922. ON r.region_id = o.region_id  
      923. WHERE o.month BETWEEN 1 AND 3  
      924. GROUP BY o.year,ROLLUP (o.year, o.month, r.name);  
      925. ERROR at line 6:  
      926. ORA-30490: Ambiguous expression in GROUP BY ROLLUP or CUBE list  
      927. 报分组列名混淆错误。但是在Oracle9i之后,则是正确的,结果如下:  
      928.   
      929.           
      930.       YEAR MONTH    REGION                                        TOTAL  
      931. ---------- ---------------- ---------------------------------------- ----------------------------------------------  
      932.       2000 1月              New England                                 1018430  
      933.       2000 1月              Mid-Atlantic                                1221394  
      934.       2000 1月              Southeast US                                 758042  
      935.       2000 1月                                                          2997866  
      936.       2000 2月              New England                                 1231492  
      937.       2000 2月              Mid-Atlantic                                 857352  
      938.       2000 2月              Southeast US                                1236846  
      939.       2000 2月                                                          3325690  
      940.       2000 3月              New England                                 1132966  
      941.       2000 3月              Mid-Atlantic                                1274062  
      942.       2000 3月              Southeast US                                1311986  
      943.       2000 3月                                                          3719014  
      944.       2001 1月              New England                                  509215  
      945.       2001 1月              Mid-Atlantic                                 610697  
      946.       2001 1月              Southeast US                                 379021  
      947.       2001 1月                                                          1498933  
      948.       2001 2月              New England                                  615746  
      949.       2001 2月              Mid-Atlantic                                 428676  
      950.       2001 2月              Southeast US                                 618423  
      951.       2001 2月                                                          1662845  
      952.       2001 3月              New England                                  566483  
      953.       2001 3月              Mid-Atlantic                                 637031  
      954.       2001 3月              Southeast US                                 655993  
      955.       2001 3月                                                          1859507  
      956.       2000                                                             10042570  
      957.       2001                                                              5021285  
      958.       2000                                                             10042570  
      959.       2001                                                              5021285  
      960.   
      961.   
      962. 因为o.year同时出现在group by中和rollup中,所以对每年的所有月份的合计重复统计,见黄色部分,在group by中同名列出现多次没有什么多大用处,只不过为了说明在Oracle9i是允许的。  
      963.   
      964. 10.2.2对复合列进行分组 首先说下复合列在Oracle中的使用,想必复合列的使用大家已经比较熟悉了。常见的复合列是在子查询和group by使用。多个列以括号包括,逗号分隔,这样的一个组被当作一个整体。比如下面是一个子查询的例子:  
      965. select id,name,trade_id from product   
      966. where (name,trade_id) in  
      967. (('易达卡',2),('畅听卡',2));  
      968.   
      969.         ID NAME         TRADE_ID  
      970. ---------- ---------- ------------------------------  
      971.         55 易达卡              2  
      972.         58 畅听卡              2  
      973.         可以看出,查询了name,trade_id分别对应('易达卡',2)和('畅听卡',2)的值。  
      974.         下面看下在单独的group by中使用复合列。例如:  
      975.         select id,name,trade_id,count(*) from product  group by (id,name),trade_id;  
      976.   
      977. 上面的语句就是先找id,name相同的放在一起,然后再找trade_id相同的放在一组,这里的括号相同于优先级。  
      978.   
      979. 在 Oracle8i中,分组只支持列的独立分组,不支持复合列的分组,Oracle9i开始支持复合列的分组,也就是上面所说的多个列用括号包括,中间短 号,括号内的列相当于一个整体,就像一个列一样,不可拆开。比如Oracle8i只允许rollup(a,b,c),但是oracle9i允许 rollup(a,(b,c)),那么将(b,c)作为一个列参与分组计算。增强了分组的功能,可以过滤某些结果。如下例:  
      980. SELECT o.year, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,  
      981. r.name region, SUM(o.tot_sales) total  
      982. FROM all_orders o JOIN region r  
      983. ON r.region_id = o.region_id  
      984. WHERE o.month BETWEEN 1 AND 3  
      985. GROUP BY ROLLUP ((o.year, o.month),r.name);  
      986.   
      987.       YEAR MONTH            REGION                                        TOTAL  
      988. ---------- ---------------- ---------------------------------------- ----------  
      989.       2000 1月              New England                                 1018430  
      990.       2000 1月              Mid-Atlantic                                1221394  
      991.       2000 1月              Southeast US                                 758042  
      992.       2000 1月                                                          2997866  
      993.       2000 2月              New England                                 1231492  
      994.       2000 2月              Mid-Atlantic                                 857352  
      995.       2000 2月              Southeast US                                1236846  
      996.       2000 2月                                                          3325690  
      997.       2000 3月              New England                                 1132966  
      998.       2000 3月              Mid-Atlantic                                1274062  
      999.       2000 3月              Southeast US                                1311986  
      1000.       2000 3月                                                          3719014  
      1001.       2001 1月              New England                                  509215  
      1002.       2001 1月              Mid-Atlantic                                 610697  
      1003.       2001 1月              Southeast US                                 379021  
      1004.       2001 1月                                                          1498933  
      1005.       2001 2月              New England                                  615746  
      1006.       2001 2月              Mid-Atlantic                                 428676  
      1007.       2001 2月              Southeast US                                 618423  
      1008.       2001 2月                                                          1662845  
      1009.       2001 3月              New England                                  566483  
      1010.       2001 3月              Mid-Atlantic                                 637031  
      1011.       2001 3月              Southeast US                                 655993  
      1012.       2001 3月                                                          1859507  
      1013.                                                                        15063855  
      1014.   
      1015.           
      1016.   
      1017. 由上面的结果分析,GROUP BY ROLLUP ((o.year, o.month),r.name)相当于group by (o.year,o.month),r.name、group by (o.year,o.month),null和group by null,null三个的union结果。与GROUP BY ROLLUP (o.year, o.month,r.name)少了group by rollup o.year,null,null。按年计算所有月份的小计。因为(o.year,o.month)是复合列,相当于一个列,不可分隔。  
      1018.   
      1019. 虽然Oracle8i未提供复合列分组的功能,但是我们可以用复合列的思想,将两个列通过连接操作,变成一个列就可以了,当然在select显示的时候必须与group by中的一致。  
      1020. 下面是oracle8i的实现:  
      1021.   
      1022. SELECT TO_CHAR(o.year)||' '||TO_CHAR(TO_DATE(o.month,'MM'),'Month')   
      1023.  Year_Month,   
      1024.  r.name region, SUM(o.tot_sales)   
      1025. FROM all_orders o JOIN region r  
      1026. ON r.region_id = o.region_id  
      1027. WHERE o.month BETWEEN 1 AND 3  
      1028. GROUP BY   
      1029. ROLLUP (TO_CHAR(o.year)||' '|| TO_CHAR(TO_DATE(o.month,'MM'),'Month'), r.name);  
      1030. 结果与oracle9i的例子一致,只不过year和month通过连接操作符变成一个列显示而已。  
      1031. group by 中使用复合列的好处在于过滤某些本来有的结果。比如上例就过滤了按年计算所有月份的小计值,但是保留了最后的合计值。如果使用前面说的局部 rollup:group by o.year,rollup(o.month,r.name)则会丢掉最后的合计值,而且包含了按年统计所有月份的小计 值,总之,应该根据具体需求,选择合适的方案。  
      1032. 10.2.3级联分组  
      1033.  在Oracle9i及后续版本,允许在group by子句后面使用多个ROLLUP,CUBE,GROUPING SETS操作,这在Oracle8i中是不允许的,在Oracle8i中值允许使用其中的一个。  
      1034. 下面研究一下rollup级联分组。  
      1035. 比如在Oracle8i中查询如下语句:  
      1036.   
      1037. SELECT o.year, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,  
      1038. r.name region, SUM(o.tot_sales) total  
      1039. FROM all_orders o JOIN region r  
      1040. ON r.region_id = o.region_id  
      1041. WHERE o.month BETWEEN 1 AND 3  
      1042. GROUP BY ROLLUP (o.year, o.month), ROLLUP(r.name);          
      1043.   
      1044. 那么报错:ERROR at line 6:  
      1045. ORA-30489: Cannot have more than one rollup/cube expression list  
      1046. 在Oracle9i中运行结果为:  
      1047.   
      1048.       YEAR MONTH    REGION                                        TOTAL  
      1049. ---------- ---------------- ---------------------------------------- -----------------------------------------------  
      1050.                             New England                                 5074332  
      1051.                             Mid-Atlantic                                5029212  
      1052.                             Southeast US                                4960311  
      1053.                                                                        15063855  
      1054.       2000                  New England                                 3382888  
      1055.       2000                  Mid-Atlantic                                3352808  
      1056.       2000                  Southeast US                                3306874  
      1057.       2000                                                             10042570  
      1058.       2000 1月              New England                                 1018430  
      1059.       2000 1月              Mid-Atlantic                                1221394  
      1060.       2000 1月              Southeast US                                 758042  
      1061.       2000 1月                                                          2997866  
      1062.       2000 2月              New England                                 1231492  
      1063.       2000 2月              Mid-Atlantic                                 857352  
      1064.       2000 2月              Southeast US                                1236846  
      1065.       2000 2月                                                          3325690  
      1066.       2000 3月              New England                                 1132966  
      1067.       2000 3月              Mid-Atlantic                                1274062  
      1068.       2000 3月              Southeast US                                1311986  
      1069.       2000 3月                                                          3719014  
      1070.       2001                  New England                                 1691444  
      1071.       2001                  Mid-Atlantic                                1676404  
      1072.       2001                  Southeast US                                1653437  
      1073.       2001                                                              5021285  
      1074.       2001 1月              New England                                  509215  
      1075.       2001 1月              Mid-Atlantic                                 610697  
      1076.       2001 1月              Southeast US                                 379021  
      1077.       2001 1月                                                          1498933  
      1078.       2001 2月              New England                                  615746  
      1079.       2001 2月              Mid-Atlantic                                 428676  
      1080.       2001 2月              Southeast US                                 618423  
      1081.       2001 2月                                                          1662845  
      1082.       2001 3月              New England                                  566483  
      1083.       2001 3月              Mid-Atlantic                                 637031  
      1084.       2001 3月              Southeast US                                 655993  
      1085.       2001 3月                                                          1859507  
      1086.   
      1087.           
      1088.           
      1089. :等价于GROUP BY ROLLUP (o.year, o.month), ROLLUP(r.name)  
      1090. GROUP BY o.year,o.month,r.name  
      1091. GROUP BY o.year,null,r.name  
      1092. GROUP BY null,null,r.name  
      1093. GROUP BY null,null,null  
      1094. GROUP BY o.year,o.month,null  
      1095. GROUP BY o.year,null,null  
      1096. 的union all的结果。提供了比rollup(o.year,o.month,r.name)更多的分组功能,多了一个GROUP BY o.year,null,r.name。  
      1097.   
      1098. group by null。因此才出现上述的6种分组结果:分组的结果为3*2=6,而没有group by null,o.month,r.name和group by null,o.month,null这两种结果。group by null,null。第2个rollup(r.name)的执行顺序是group by r.namegroup by o.year,null        当 在group by中使用多个rollup,cube,grouping sets操作的时候,我们叫这样的分组为级联分组。级联分组的结果就是产生每个 单独分组操作的交叉列表,但是要符合每个操作的处理步骤,比如上面的 GROUP BY ROLLUP (o.year, o.month), ROLLUP(r.name)操作,第1个rollup(o.year,o.month)的执行顺序是group by o.year,o.month  
      1099.   
      1100. 根据上述的规则,我们将rollup(o.year,o.month)改为cube(o.year,o.month),那么cube的计算种类是4中,后面的rollup(r.name)为两种,那么这种级联分组应该有相当于group by的分类为4*2=8种,比rollup(o.year,o.month),rollup(r.name)多了group by null,o.month,r.name和group by null,o.month,null这两种结果。我们看下结果:  
      1101.   
      1102. SELECT o.year, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,  
      1103. r.name region, SUM(o.tot_sales) total  
      1104. FROM all_orders o JOIN region r  
      1105. ON r.region_id = o.region_id  
      1106. WHERE o.month BETWEEN 1 AND 3  
      1107. GROUP BY cube (o.year, o.month), ROLLUP(r.name);  
      1108.   
      1109.  YEAR MONTH            REGION                                        TOTAL  
      1110. ---------- ---------------- ---------------------------------------- ----------  
      1111.       2000 1月              New England                                 1018430  
      1112.       2001 1月              New England                                  509215  
      1113.       2000 1月              Mid-Atlantic                                1221394  
      1114.       2001 1月              Mid-Atlantic                                 610697  
      1115.       2000 1月              Southeast US                                 758042  
      1116.       2001 1月              Southeast US                                 379021  
      1117.       2000 2月              New England                                 1231492  
      1118.       2001 2月              New England                                  615746  
      1119.       2000 2月              Mid-Atlantic                                 857352  
      1120.       2001 2月              Mid-Atlantic                                 428676  
      1121.       2000 2月              Southeast US                                1236846  
      1122.       2001 2月              Southeast US                                 618423  
      1123.       2000 3月              New England                                 1132966  
      1124.       2001 3月              New England                                  566483  
      1125.       2000 3月              Mid-Atlantic                                1274062  
      1126.       2001 3月              Mid-Atlantic                                 637031  
      1127.       2000 3月              Southeast US                                1311986  
      1128.       2001 3月              Southeast US                                 655993  
      1129.              1月              New England                                 1527645  
      1130.             1月               Mid-Atlantic                                1832091  
      1131.              1月              Southeast US                                1137063  
      1132.              2月              New England                                 1847238  
      1133.             2月              Mid-Atlantic                                1286028  
      1134.              2月              Southeast US                                1855269  
      1135.              3月              New England                                 1699449  
      1136.             3月              Mid-Atlantic                                1911093  
      1137.              3月              Southeast US                                1967979  
      1138.       2000                  New England                                 3382888  
      1139.       2001                  New England                                 1691444  
      1140.                             New England                                 5074332  
      1141.       2000                  Mid-Atlantic                                3352808  
      1142.       2001                  Mid-Atlantic                                1676404  
      1143.                             Mid-Atlantic                                5029212  
      1144.       2000                  Southeast US                                3306874  
      1145.       2001                  Southeast US                                1653437  
      1146.                             Southeast US                                4960311  
      1147.             1月                                                          4496799  
      1148.             2月                                                          4988535  
      1149.             3月                                                          5578521  
      1150.       2000                                                             10042570  
      1151.       2001                                                              5021285  
      1152.                                                                        15063855  
      1153.       2000 1月                                                          2997866  
      1154.       2001 1月                                                          1498933  
      1155.       2000 2月                                                          3325690  
      1156.       2001 2月                                                          1662845  
      1157.       2000 3月                                                          3719014  
      1158.       2001 3月                                                          1859507  
      1159.           
      1160.         分析结果:黄色部分就是与使用rollup的时候多出的结果,正好是group by null,o.month,r.name和group by null,o.month,null的结果,其他与rollup(o.year,o.month),rollup(r.name)完全一致。  
      1161.   
      1162.  下面研究一下CUBE级联分组。  
      1163.  有了级联分组,可以将rollup与cube之间相互转换,比如:  
      1164.  SELECT o.year, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,  
      1165. r.name region, SUM(o.tot_sales) total  
      1166. FROM all_orders o JOIN region r  
      1167. ON r.region_id = o.region_id  
      1168. WHERE o.month BETWEEN 1 AND 3  
      1169. GROUP BY ROLLUP(o.year),  ROLLUP (o.month), ROLLUP (r.name);  
      1170.   
      1171. 3个单列的rollup级联分组,每个分组有2种,那么总共有2^3=8种,正好相当于下列cube运算的结果:  
      1172. SELECT o.year, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,  
      1173. r.name region, SUM(o.tot_sales) total  
      1174. FROM all_orders o JOIN region r  
      1175. ON r.region_id = o.region_id  
      1176. WHERE o.month BETWEEN 1 AND 3  
      1177. GROUP BY CUBE (o.year, o.month, r.name);  
      1178.   
      1179. 再来考虑一个问题,如果对于cube级联分组,会出现什么情况下,我们知道cube是对所有可能性进行分组,有n个列,分组的种类是2^n个。那么cube级联分组不管怎么拆分,实际上和单独的cube所有列的结果是一致的。比如下列语句和上面的一致(简写如下):  
      1180. GROUP BY CUBE (o.year, o.month), CUBE (r.name);  
      1181. GROUP BY CUBE (o.year), CUBE (o.month, r.name);  
      1182. GROUP BY CUBE (o.year), CUBE (o.month), CUBE (r.name);  
      1183.   
      1184. 都是有8种分组方法,当然如果和其它的比如rollup联合起来,cube拆开与不拆开的结果也是一致的。  
      1185.   
      1186. 10.2.3.1 GROUPING SETS级联分组  
      1187.   
      1188. Grouping Sets 的级联分组很有用,因为可以知道,grouping sets分组只是对单列分别进行小计统计,比如有n列就是分别对这个n列进行单列小计,有n种结果。 但是当我们需要使用Grouping sets获得复合列的小计的时候,那么单独的grouping sets分组就没有办法了,但是可以使用级联 grouping sets操作。同rollup和cube的级联分组一样,比如 grouping sets(a,b),grouping sets(c,d)那么有2*2=4种统计方法:分别是group by(a,c)、  
      1189. group by(a,d)、group by(b,c)和group by(b,c),即列的交叉分组。如:  
      1190. SELECT o.year, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,  
      1191. r.name region, SUM(o.tot_sales) total  
      1192. FROM all_orders o JOIN region r  
      1193. ON r.region_id = o.region_id  
      1194. WHERE o.month BETWEEN 1 AND 3  
      1195. GROUP BY GROUPING SETS (o.year, o.month), GROUPING SETS (r.name);  
      1196.   
      1197.      YEAR MONTH            REGION                                        TOTAL  
      1198. --------- ---------------- ---------------------------------------- ----------  
      1199.           3月              Mid-Atlantic                                1911093  
      1200.           1月              New England                                 1527645  
      1201.           2月              Southeast US                                1855269  
      1202.           2月              Mid-Atlantic                                1286028  
      1203.           1月              Southeast US                                1137063  
      1204.           1月              Mid-Atlantic                                1832091  
      1205.           3月              New England                                 1699449  
      1206.           3月              Southeast US                                1967979  
      1207.           2月              New England                                 1847238  
      1208.      2000                  Mid-Atlantic                                3352808  
      1209.      2001                  New England                                 1691444  
      1210.      2000                  Southeast US                                3306874  
      1211.      2001                  Southeast US                                1653437  
      1212.      2000                  New England                                 3382888  
      1213.      2001                  Mid-Atlantic                                1676404  
      1214.   
      1215. 上面的黄色部分就是对(o.month,r.name)的分组结果,红色部分是(o.year,r.name)的分组结果,有两个复合列的分组统计。  
      1216.   
      1217.  下面我们对上面的例子,增加一个列,看看结果:  
      1218. SELECT o.year, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,  
      1219. r.name region, SUM(o.tot_sales) total  
      1220. FROM all_orders o JOIN region r  
      1221. ON r.region_id = o.region_id  
      1222. WHERE o.month BETWEEN 1 AND 3  
      1223. GROUP BY GROUPING SETS (o.year, o.month), GROUPING SETS (o.year, r. name);  
      1224.           
      1225.       YEAR MONTH            REGION                                        TOTAL  
      1226. ---------- ---------------- ---------------------------------------- ----------  
      1227.           3月              Mid-Atlantic                                1911093  
      1228.            1月              New England                                 1527645  
      1229.            2月              Southeast US                                1855269  
      1230.           2月              Mid-Atlantic                                1286028  
      1231.            1月              Southeast US                                1137063  
      1232.           1月              Mid-Atlantic                                1832091  
      1233.            3月              New England                                 1699449  
      1234.            3月              Southeast US                                1967979  
      1235.            2月              New England                                 1847238  
      1236.       2000                  Mid-Atlantic                                3352808  
      1237.       2001                  New England                                 1691444  
      1238.       2000                  Southeast US                                3306874  
      1239.       2001                  Southeast US                                1653437  
      1240.       2000                  New England                                 3382888  
      1241.       2001                  Mid-Atlantic                                1676404  
      1242.       2000 1月                                                          2997866  
      1243.       2000 2月                                                          3325690  
      1244.       2000 3月                                                          3719014  
      1245.       2000                                                             10042570  
      1246.       2001 1月                                                          1498933  
      1247.       2001 2月                                                          1662845  
      1248.       2001 3月                                                          1859507  
      1249.       2001                                                              5021285  
      1250.   
      1251.   
      1252. GROUPING SETS (o.year, o.month), GROUPING SETS (o.year, r. name) 相当于group by(o.year,o.year)等价于 group by o.year,group by(o.year,r.name),group by(o.month,o.year),group by(o.month,r.name) 对应上面4个区域的结果。  
      1253.   
      1254.  其 实,因为最终的结果可以转化为对应的group by分组的union结果,而group by分组和列的顺序没有关系,因此级联 grouping sets和列的顺序也没有关系,只要分组的种类一致即可,比如上面的等价 于: GROUPING SETS (o.year, r.name), GROUPING SETS (o.year, o.month);  
      1255. GROUPING SETS (o.month, o.year), GROUPING SETS (r.name, o.year);  
      1256.   
      1257. 另外,在一个group by中可以同时使用grouping sets,cube,rollup,比如:  
      1258. SELECT o.year, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,  
      1259. r.name region, SUM(o.tot_sales) total  
      1260. FROM all_orders o JOIN region r  
      1261. ON r.region_id = o.region_id  
      1262. WHERE o.month BETWEEN 1 AND 3  
      1263. GROUP BY GROUPING SETS (o.month, o.year), ROLLUP(r.name), CUBE (o.year);  
      1264. 上面的有8种统计结果,但是这样的语句其实一般意义不大,如果需要这样复杂的统计,需要仔细分析。 
  • 相关阅读:
    收藏CSS经典技巧
    理解这26句话将不再烦恼
    包转发率得计算和背板带宽的计算
    mysql 建表 AUTO_INCREMENT , 数据类型 VARCHAR
    Linux Wine with *.bat *.exe ( Photoshop and etc.. )
    [转载]expect spawn、linux expect 用法小记
    sqlmap.py Database injection and hak
    xls===>csv tables===via python ===> sqlite3.db
    sftp 服务器外网访问设置
    vsftp FTP服务器外网访问设置
  • 原文地址:https://www.cnblogs.com/lcword/p/5521340.html
Copyright © 2011-2022 走看看