zoukankan      html  css  js  c++  java
  • 使用group by rollup和group by cube后的辅助函数

    本文主要介绍,报表在使用group by rollup和group by cube后的辅助函数。

    CREATE TABLE TEST8
    (    
       "ID" NUMBER,     
       "ORDERID" NUMBER, 
       "PRODUCTID" NUMBER, 
       "PRICE" NUMBER(10,2), 
       "QUANTITY" NUMBER
    )
    insert into TEST8 (ID, ORDERID, PRODUCTID, PRICE, QUANTITY) values (1, 1, 1, 3, 10);
    insert into TEST8 (ID, ORDERID, PRODUCTID, PRICE, QUANTITY) values (2, 1, 2, 4, 5);
    insert into TEST8 (ID, ORDERID, PRODUCTID, PRICE, QUANTITY) values (3, 1, 3, 10, 2);
    insert into TEST8 (ID, ORDERID, PRODUCTID, PRICE, QUANTITY) values (4, 2, 1, 3, 6);
    insert into TEST8 (ID, ORDERID, PRODUCTID, PRICE, QUANTITY) values (5, 2, 2, 4, 6);

    基础数据

    1、GROUPING函数

    使用GROUPING函数处理汇总结果(在使用group by rollup和group by cube后的结果集)中的空值。

    select orderid,productid,count(orderid) ordercount from test8 group by cube(orderid,productid) order by orderid;

    结果集按照orderid和productid进行汇总之后,出现了很多的空值,具体原因参考哥前面的随笔 ,so,必须解决这个问题,因为null值对报表结果来说没什么用,我们大致都会用0,'空','NULL'之类,来表示空值,所以GROUPING函数就是来干这个的.看代码:

    select GROUPING(orderid) orderid,productid,count(orderid) ordercount from test8 group by cube(orderid,productid) order by orderid;

    对比上面的没有使用GROUPING函数的结果集我们发现

    当orderid为null值的时候grouping(orderid)的值为1,反之为0

    所以:根据这个特点我们可以推断出GROUPING函数的用法:

    GROUPING(字段),如果字段值为null,GROUPING(字段)返回1,反之返回0。

    通过GROUPING(字段名)的这个特点,在结果case when then else end函数,就可以将null值修改为任何字段名类型的值了,代码如下:

    select case GROUPING(orderid) when 1 then 0 else orderid end orderid,productid,count(orderid) ordercount from test8 group by cube(orderid,productid) order by orderid;

    null值全部改为了0

    2、GROUPING  SETS函数

    哥前面的随笔一样,不知道它的功能没关系,先试一试,在根据结果集推出来他的功能,不多说,上代码:

    i、现在需要求出每个订单下每个产品的订单数

    (1)group by解决方法:

    select orderid,productid,count(orderid) from test8 group by (orderid,productid) order by orderid 

    (2)group by grouping sets解决方案

    这边因为不知道他的功能,那么就直接上代码猜:

    a、猜想一:grouping sets(orderid,productid)

    select orderid,productid,count(orderid) from test8 group by grouping sets(orderid,productid) order by orderid 

    根据结果集很容易的发现,group by grouping sets(orderid,productid)的结果集等于group by orderid 和group by productid的合集,

    下面验证猜想:

    select orderid,null productid,count(orderid) ordercount from test8 group by(orderid) 
    union
    select null orderid,productid,count(orderid) ordercount from test8 group by(productid) 

    ok,我们的猜想是正确,但是grouping sets(orderid,productid)并不能解i的需求,于是继续猜

    b、猜想二:group by grouping sets(orderid,productid)

    select orderid,productid,count(orderid) ordercount from test8 group by grouping sets((orderid,productid)) order by orderid 

    ok,猜想二符合i提出的需求

    ii、总结grouping sets的功能

    根据上面的猜想大致可以推出grouping sets的功能:grouping by是group by的集合

    GROUP BY GROUPING SETS (A,B,C)  等价与  GROUP BY A  
                                            UNION ALL  
                                            GROUP BY B  
                                            UNION ALL  
                                            GROUP BY C  

    注意:grouping sets的特殊用法,grouping sets内部的最小单位是单个字段,其次是一个多个字段的几个用(字段1,字段2,......)表示,但是不支持嵌套括号,也没有必要,因为大多数情况下的报表都是2维的。

    GROUP BY GROUPING SETS ((A,B,C))  等价与  GROUP BY A,B,C  
       
       
    GROUP BY GROUPING SETS (A,(B,C))  等价与  GROUP BY A  
                                              UNION ALL  
                                              GROUP BY B,C  

    我们还可以混合使用,如下:

    GROUP BY A                     等价于  GROUP BY A  
            ,B                                     ,B  
            ,GROUPING SETS ((B,C))                 ,C  
       
       
    GROUP BY A                    等价于  GROUP BY A,B,C  
            ,B                            UNION ALL  
            ,GROUPING SETS (B,C)          GROUP BY A,B  
       
       
    GROUP BY A                    等价于 GROUP BY A,B,C  
            ,B                           UNION ALL  
            ,C                           GROUP BY A,B,C  
            ,GROUPING SETS (B,C)   

    iii、Group by  Grouping sets解决的问题:

    更加灵活的处理一些报表的统计工作,因为使用group by rollup 和group by cube都是固定格式的统计报表模式,当你给定三个需要分组统计的字段(A,B,C),前者是

    select count(*)  from   tb ------->group by A------>group by B ------->group by C  然后将几个结果集union all一下,后者则是通过类似选择排序的方式联合结果集(不理解的话,参考哥前面的随笔),这两种统计模式不够灵活。

    所以Group by  Grouping sets就是一种足够灵活的方式,来获取我们想要的统计报表。

    3、GROUP BY ,CUBE 或ROLLUP 中同时使用一列的处理

    i、问题:在日常开发中可能会存在GROUP BY 或者GROUP BY CUBE 或者GROUP BY ROLLUP或者它们中组合使用到同一列的情况,那么就会出现重复的数据行,代码如下:

    select orderid,productid,count(orderid) ordercount from test8 group by orderid,rollup(orderid,productid)

    前面group by已经对orderid做了一次分组统计,后面rollup又对其做了一次分组统计,所以

    出现了红框内的情况

    ii、解决方案:

    a、第一步:使用GROUP_ID()函数,这个函数的作用检索出每一个数据行在表中重复出现的次数,当然这个函数只在有GROUP BY或者GROUP BY ROLLUP 或者GROUP BY CUBE语句中的某一个存在的语句中可以使用,在其他语句中不能使用,代码如下:

    select orderid,productid,GROUP_ID(),count(orderid) ordercount from test8 group by orderid,rollup(orderid,productid) 

    GROUP_ID()方法显示红框内的两条数据重复出现了一次,那么这两条数据就需要过滤

    b、下面使用HAVING(相当于where,但是having只能用于分组函数的数据过滤,只能用于包含group by的语句中) 来过滤重复的数据,代码如下:

    select orderid,productid,GROUP_ID(),count(orderid) ordercount from test8 group by orderid,rollup(orderid,productid) HAVING GROUP_ID()=0

    ok,数据成功过滤

  • 相关阅读:
    用.NET读取Flash格式文件信息
    通过ASP.NET页面重启服务器
    Webservice优点与缺点
    iClient 6R for Flex移动端开发的Q&A
    GIS十年路
    脚本调用命令行
    FME的简单介绍
    GIS从信息化到领域化(一)
    GIS从信息化到领域化(二)
    理性的看待地理信息共享交换平台建设
  • 原文地址:https://www.cnblogs.com/GreenLeaves/p/6566409.html
Copyright © 2011-2022 走看看