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,数据成功过滤

  • 相关阅读:
    防删没什么意思啊,直接写废你~
    绝大多数情况下,没有解决不了的问题,只有因为平时缺少练习而惧怕问题的复杂度,畏惧的心理让我们选择避让,采取并不那么好的方案去解决问题
    Java 模拟面试题
    Crossthread operation not valid: Control 'progressBar1' accessed from a thread other than the thread it was created on
    一步步从数据库备份恢复SharePoint Portal Server 2003
    【转】理解 JavaScript 闭包
    Just For Fun
    The database schema is too old to perform this operation in this SharePoint cluster. Please upgrade the database and...
    Hello World!
    使用filter筛选刚体碰撞
  • 原文地址:https://www.cnblogs.com/GreenLeaves/p/6566409.html
Copyright © 2011-2022 走看看