ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 高级分组4

高级分组4

原创 Linux操作系统 作者:wengjie_0627 时间:2011-08-09 10:30:48 0 删除 编辑
10.1.5部分CUBE
        部分CUBE和部分ROLLUP类似,把不想要的小计和合计的列放到group by中,不放到cube中就可以了。比如:
SELECT r.name region, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,
SUM(o.tot_sales) sums
FROM all_orders o JOIN region r
ON r.region_id = o.region_id
GROUP BY r.name, CUBE(o.month);
REGION                                   MONTH                  SUMS
---------------------------------------- ---------------- -------------------------------------------------
New England                                                 19756923
New England                              1月                 1527645
New England                              2月                 1847238
New England                              3月                 1699449
New England                              4月                 1792866
New England                              5月                 1698855
New England                              6月                 1510062
New England                              7月                 1678002
New England                              8月                 1642968
New England                              9月                 1726767
New England                              10月                1648944
New England                              11月                1384185
New England                              12月                1599942
Mid-Atlantic                                                18923298
Mid-Atlantic                             1月                 1832091
Mid-Atlantic                             2月                 1286028
Mid-Atlantic                             3月                 1911093
Mid-Atlantic                             4月                 1623438
Mid-Atlantic                             5月                 1778805
Mid-Atlantic                             6月                 1504455
Mid-Atlantic                             7月                 1820742
Mid-Atlantic                             8月                 1381560
Mid-Atlantic                             9月                 1178694
Mid-Atlantic                             10月                1530351
Mid-Atlantic                             11月                1598667
Mid-Atlantic                             12月                1477374
Southeast US                                                20605485
Southeast US                             1月                 1137063
Southeast US                             2月                 1855269
Southeast US                             3月                 1967979
Southeast US                             4月                 1830051
Southeast US                             5月                 1983282
Southeast US                             6月                 1705716
Southeast US                             7月                 1670976
Southeast US                             8月                 1436295
Southeast US                             9月                 1905633
Southeast US                             10月                1610523
Southeast US                             11月                1661598
Southeast US                             12月                1841100
       
        从上面结果可以看出,当将区域名从cube中移到group by中,则总会按区域名统计,则结果中移除了按月小计和总计的结果。我们可以发现,如果cube中只有一个列,那么和rollup的结果一致,也就是上面的语句等价于:
SELECT r.name region, TO_CHAR(TO_DATE(o.month, 'MM'), 'Month') month,
SUM(o.tot_sales) sums
FROM all_orders o JOIN region r
ON r.region_id = o.region_id
GROUP BY r.name, rollup(o.month);

注:
        对上面的rollup和cube的小计或总计中,有的列是null的表示按此列小计,如果前面的非汇总列都是null则表示总计。在实际应用中不可能把这些null给别人看,因为别人不知道你是用rollup或cube计算的。这时候可能会用到nvl或其它的转换,详细请看下节grouing函数。

10.1.6 GROUPING函数
        在实际应用中,使用rollup或cube可以统计小计和合计的值,那么在小计和合计中会出现列的值为NULL的情况,客户就不知道什么意思了。为了增强客户的可读性,我们可能会想到使用NVL函数,如下:
SELECT NVL(TO_CHAR(o.year), 'All Years') year,
NVL(TO_CHAR(TO_DATE(o.month, 'MM'), 'Month'), 'First Quarter') month,
NVL(r.name, 'All Regions') region, SUM(o.tot_sales) sums
FROM all_orders o JOIN region r
ON r.region_id = o.region_id
WHERE o.month BETWEEN 1 AND 3
GROUP BY ROLLUP (o.year, o.month, r.name);
YEAR       MONTH                REGION                     SUMS
---------- -------------------- -------------------- -----------------------------------------------------
2000       1月                  New England             1018430
2000       1月                  Mid-Atlantic            1221394
2000       1月                  Southeast US             758042
2000       1月                  All Regions             2997866
2000       2月                  New England             1231492
2000       2月                  Mid-Atlantic             857352
2000       2月                  Southeast US            1236846
2000       2月                  All Regions             3325690
2000       3月                  New England             1132966
2000       3月                  Mid-Atlantic            1274062
2000       3月                  Southeast US            1311986
2000       3月                  All Regions             3719014
2000       First Quarter        All Regions            10042570
2001       1月                  New England              509215
2001       1月                  Mid-Atlantic             610697
2001       1月                  Southeast US             379021
2001       1月                  All Regions             1498933
2001       2月                  New England              615746
2001       2月                  Mid-Atlantic             428676
2001       2月                  Southeast US             618423
2001       2月                  All Regions             1662845
2001       3月                  New England              566483
2001       3月                  Mid-Atlantic             637031
2001       3月                  Southeast US             655993
2001       3月                  All Regions             1859507
2001       First Quarter        All Regions             5021285
All Years  First Quarter        All Regions            15063855
       
        可以看出,原来是NULL的都被有意义的值代替,增加了用户可读性。使用NVL函数对这个例子来说是非常适合的,但是另外一个情况我们要考虑一下,如果这些列中本身就有NULL值的存在,那么我们使用NVL函数之后,到底是小计还是本身的值呢???带着这个问题,我们来看一个例子:
SELECT * FROM disputed_orders;
        ORDER_NBR CUST_NBR SALES_EMP_ID SALE_PRICE ORDER_DT    EXPECTED_SHIP_DT  STATUS
--------- -------- ------------ ---------- ----------- -------------- ---------
     1001        1         7354         99 22-jul-2001 23-jul-2001    DELIVERED
     1000        1         7354            19-jul-2001 24-jul-2001
     1002        5         7368            12-jul-2001 25-jul-2001
     1003        4         7654         56 16-jul-2001 26-jul-2001    DELIVERED
     1004        4         7654         34 18-jul-2001 27-jul-2001    PENDING
     1005        8         7654         99 22-jul-2001 24-jul-2001    DELIVERED
     1006        1         7354            22-jul-2001 28-jul-2001
     1007        5         7368         25 20-jul-2001 22-jul-2001    PENDING
     1008        5         7368         25 21-jul-2001 23-jul-2001    PENDING
     1009        1         7354         56 18-jul-2001 22-jul-2001    DELIVERED
     1012        1         7354         99 22-jul-2001 23-jul-2001    DELIVERED
     1011        1         7354            19-jul-2001 24-jul-2001
     1015        5         7368            12-jul-2001 25-jul-2001
     1017        4         7654         56 16-jul-2001 26-jul-2001    DELIVERED
     1019        4         7654         34 18-jul-2001 27-jul-2001    PENDING
     1021        8         7654         99 22-jul-2001 24-jul-2001    DELIVERED
     1023        1         7354            22-jul-2001 28-jul-2001
     1025        5         7368         25 20-jul-2001 22-jul-2001    PENDING
     1027        5         7368         25 21-jul-2001 23-jul-2001    PENDING
     1029        1         7354         56 18-jul-2001 22-jul-2001    DELIVERED
       
        可以看到,有的status值为NULL。那么现在我们需要汇总每个customer对应状态的数目以及所有customer每个状态的数目最后合计。使用NVL函数如下:
SELECT NVL(TO_CHAR(cust_nbr), 'All Customers') customer,
NVL(status, 'All Status') status,
COUNT(*) FROM disputed_orders
GROUP BY CUBE(cust_nbr, status);
CUSTOMER             STATUS                 COUNT(*)
-------------------- -------------------- ----------
All Customers        All Status                    6
All Customers        All Status                   20
All Customers        PENDING                       6
All Customers        DELIVERED                     8
1                    All Status                    4
1                    All Status                    8
1                    DELIVERED                     4
4                    All Status                    4
4                    PENDING                       2
4                    DELIVERED                     2
5                    All Status                    2
5                    All Status                    6
5                    PENDING                       4
8                    All Status                    2
8                    DELIVERED                     2

        从上面的结果可以看出,这种使用NVL函数没有任何意义,得出的结果混淆,比如黄色部分,对用户1有两个all status,其实其中一个是本身表中的status为null,因此统计混乱。
        Oracle为了解决这个问题,专门有一个grouping函数。grouping函数解释如下:
1.        grouping函数只有一个参数,接受来自于group by,rollup,cube,grouping sets的列。
2.        grouping函数对rollup,cube的汇总列(小计或合计行的列值)置为1,其他的非汇总列置为0,如在单独的group by中使用肯定全为0,因为没有通过rollup或cube的小计或合计行。
3.        grouping函数可以有效地避免nvl函数带来的小计或合计与本身表中有null带来的混淆问题。
4.        使用方式为:
SELECT  . . .  [GROUPING(grouping_column_name)]  . . .
FROM  . . .
GROUP BY  . . .  {ROLLUP | CUBE} (grouping_column_name)
下面用grouping函数改写上面的的例子如下:
SELECT  decode(grouping(cust_nbr),1,'ALL CUSTOMER',cust_nbr) customer,
decode(grouping(status),1,'ALL STATUS',nvl(status,'原始值为空')) status,
COUNT(*) FROM disputed_orders
GROUP BY CUBE(cust_nbr, status);
CUSTOMER             STATUS                 COUNT(*)
-------------------- -------------------- ----------
ALL CUSTOMER         原始值为空                    6
ALL CUSTOMER         ALL STATUS                   20
ALL CUSTOMER         PENDING                       6
ALL CUSTOMER         DELIVERED                     8
1                    原始值为空                    4
1                    ALL STATUS                    8
1                    DELIVERED                     4
4                    ALL STATUS                    4
4                    PENDING                       2
4                    DELIVERED                     2
5                    原始值为空                    2
5                    ALL STATUS                    6
5                    PENDING                       4
8                    ALL STATUS                    2
8                    DELIVERED                     2               
使用decode和grouping函数,避免了null的问题,现在黄色部分对status为null的也统计了。汇总和status为null的不再混淆。

再看一个例子:
SELECT DECODE(GROUPING(o.year), 1, 'All Years', o.year) Year,
DECODE(GROUPING(o.month), 1, 'All Months',
TO_CHAR(TO_DATE(o.month, 'MM'), 'Month')) Month,
DECODE(GROUPING(r.name), 1, 'All Regions', r.name) Region, SUM(o.tot_sales) sums
FROM all_orders o JOIN region r
ON r.region_id = o.region_id
WHERE o.month BETWEEN 1 AND 3
GROUP BY ROLLUP (o.year, o.month, r.name);
YEAR       MONTH                REGION                     SUMS
---------- -------------------- -------------------- ----------
2000       January              New England             1018430
2000       January              Mid-Atlantic            1221394
2000       January              Southeast US             758042
2000       January              All Regions             2997866
2000       February             New England             1231492
2000       February             Mid-Atlantic             857352
2000       February             Southeast US            1236846
2000       February             All Regions             3325690
2000       March                New England             1132966
2000       March                Mid-Atlantic            1274062
2000       March                Southeast US            1311986
2000       March                All Regions             3719014
2000       All Months           All Regions            10042570
2001       January              New England              509215
2001       January              Mid-Atlantic             610697
2001       January              Southeast US             379021
2001       January              All Regions             1498933
2001       February             New England              615746
2001       February             Mid-Atlantic             428676
2001       February             Southeast US             618423
2001       February             All Regions             1662845
2001       March                New England              566483
2001       March                Mid-Atlantic             637031
2001       March                Southeast US             655993
2001       March                All Regions             1859507
2001       All Months           All Regions             5021285
All Years  All Months           All Regions            15063855

        使用deocode(当然也可以用case,没有decode简单)联合grouping函数,使报表的小计和合计列描述有意义,避免原始数据有null而使用nvl函数带来混淆的问题。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/24984814/viewspace-704464/,如需转载,请注明出处,否则将追究法律责任。

上一篇: 高级分组3
下一篇: 高级分组5
请登录后发表评论 登录
全部评论

注册时间:2011-05-19

  • 博文量
    50
  • 访问量
    30261