SQL基础之GROUPING

1.grouping setssql

  记得前几天第一次接触grouping sets时,笔者的感受是一脸懵逼。数据库

  后来一不当心看到msdn上对grouping sets的说明,顿时豁然开朗,其实grouping sets就是由多个group by联合起来,关系以下。函数

  select A , B from table group by grouping sets(A, B)   等价于 性能

  select A , null as B  from table group by A   spa

  union all  3d

  select null as A ,  B  from table group by B code

  为了更好的理解我建立了teacher表,表数据以下,查询结果集中左边的为使用union all的group by字句,右边的为使用grouping sets的结果集。blog

  

select  null as teacherAddress,MAX(teacherSalary),ascriptionInstitute from teacher group by  ascriptionInstitute
union all
select  teacherAddress,MAX(teacherSalary),NULL as ascriptionInstitute from teacher group by  teacherAddress

select  teacherAddress,MAX(teacherSalary),ascriptionInstitute from teacher group by  GROUPING SETS (ascriptionInstitute,teacherAddress)

      

   上面提到grouping sets是等价于带union all的group by子句,之因此是等价而不是等于,从二者结果集中的对比就能够一目了之,那就是它们的顺序不同。这说明grouping sets并不仅是group by的语法糖,这二者内部的执行过程应该是全然不一样的,在百度过程当中发现大多数答案都是这句话:“聚合是一次性从数据库中取出全部须要操做的数据,在内存中对数据库进行聚合操做并生成结果。而UNION ALL是屡次扫描表,将返回的结果进行UNION操做。性能方面grouping sets能减小IO操做但会增长CPU占用时间”。我不理解的地方是一次性取出数据后,是如何在内存中进行聚合操做的?结果集虽然顺序不同但数据是相同的,这说明依旧进行了联合操做而这个联合操做并非屡次扫描表,关键内部屡次是如何扫描的我很好奇?对于性能我想知道为何会这样子而不是看到现象。另外在grouping sets中若是将括号中的参数换个位置那么结果也将改变,这说明结果集中的顺序与参数的位置也有关,这让我更加好奇grouping sets的内部执行过程了。ip

select  MAX(teacherSalary),ascriptionInstitute ,teacherAddress from teacher group by  GROUPING SETS (ascriptionInstitute,teacherAddress)
select  MAX(teacherSalary),ascriptionInstitute ,teacherAddress from teacher group by  GROUPING SETS (teacherAddress,ascriptionInstitute)

           

 2.grouping( )内存

  grouping函数用来区分NULL值,这里NULL值有2种状况,一是本来表中的数据就为NULL,二是由rollup、cube、grouping sets生成的NULL值。

  当为第一种状况中的空值时,grouping(NULL)返回0;当为第二种状况中的空值时,grouping(NULL)返回1。实例以下,从结果中能够看到第二个结果集中本来为null的数据因为grouping函数为1,故显示ROLLUP-NULL字符串。

select teacherAddress,ascriptionInstitute,COUNT(teacherId ) from teacher group by teacherAddress,ascriptionInstitute
select teacherAddress,ascriptionInstitute,COUNT(teacherId )  from teacher group by rollup(teacherAddress,ascriptionInstitute)

select ISNULL(teacherAddress,case when GROUPING(teacherAddress)=1 then 'ROLLUP-NULL' end) as teacherAddress,
            ISNULL(ascriptionInstitute,case when GROUPING(ascriptionInstitute)=1 then 'ROLLUP-NULL' end) as ascriptionInstitute,
            COUNT(teacherId )  
            from teacher group by rollup(teacherAddress,ascriptionInstitute)

  

 3.grouping_id( )

  grouping_id函数也是计算分组级别的函数,注意若是要使用grouping_id函数那必须得有group by字句,并且group by字句的中的列与grouping_id函数的参数必须相等。好比group by A,B,那么必须使用grouping_id(A,B)。下面用一个等效关系来讲明grouping_id()与grouping()的联系,grouping_id(A, B)等效于grouping(A) + grouping(B),但要注意这里的+号不是算术相加,它表示的是二进制数据组合在一块儿,好比grouping(A)=1,grouping(B)=1,那么grouping_id(A, B)=11B,也就是十进制数3。原来的表数据执行下面的sql语句结果太多效果不明显,因此我改了下表数据,不过对比两个结果集效果很明显。

select ISNULL(teacherAddress,case when GROUPING(teacherAddress)=1 then 'ROLLUP-NULL' end) as teacherAddress,
            ISNULL(ascriptionInstitute,case when GROUPING(ascriptionInstitute)=1 then 'ROLLUP-NULL' end) as ascriptionInstitute,
            ISNULL(teacherSex,case when GROUPING(teacherSex)=1 then 'ROLLUP-NULL' end) as teacherSex,
            COUNT(teacherId )  
            from teacher group by rollup(teacherAddress,ascriptionInstitute,teacherSex)
            
select ISNULL(teacherAddress,case when GROUPING(teacherAddress)=1 then 'ROLLUP-NULL' end) as teacherAddress,
            ISNULL(ascriptionInstitute,case when GROUPING(ascriptionInstitute)=1 then 'ROLLUP-NULL' end) as ascriptionInstitute,
            ISNULL(teacherSex,case when GROUPING(teacherSex)=1 then 'ROLLUP-NULL' end) as teacherSex,
            COUNT(teacherId ) as '数量' ,
            GROUPING_ID(teacherAddress,ascriptionInstitute,teacherSex) 
            from teacher group by rollup(teacherAddress,ascriptionInstitute,teacherSex)

      

相关文章
相关标签/搜索