玩转数据库之 Group by Grouping

有的时候我们要从数据库里把数据组织成树结构再展现到页面上

像下面这样

今天我们用Group 和Grouping实现它,并总结一下它俩。

先看一下概念,再用代码一点一点去理解它们,最后我会给出完整的代码

Group By : 语句用于结合合计函数,根据一个或多个列对结果集进行分组。

Grouping :指示是否聚合 GROUP BY 列表中的指定列表达式。 在结果集中,如果 GROUPING 返回 1 则指示聚合;

返回 0 则指示不聚合。 如果指定了 GROUP BY,则 GROUPING 只能用在 SELECT <select> 列表、HAVING 和 ORDER BY 子句中。

ROLLUP :生成简单的 GROUP BY 聚合行以及小计行或超聚合行,还生成一个总计行。

让我们先建一个数据库,并添加一些数据

use master 
go
if exists(select 1 from sysdatabases where name ='MyGroupDB')
    ALTER DATABASE MyGroupDB SET SINGLE_USER with ROLLBACK IMMEDIATE 
    drop database MyGroupDB
go
 
create database MyGroupDB
go
use MyGroupDB
go
 
create Table Category
(
    Category_ID int identity(1,1),
    Category_Name varchar(100)
)
go
create Table Product
(
    Product_ID int identity(1,1),
    CategoryID int ,
    Product_Name varchar(100)
)
go
insert into Category values('手机')
insert into Category values('台式机')
insert into Category values('数码相机')
go
 
insert into Product values(1,'诺基亚')
insert into Product values(1,'三星')
insert into Product values(1,'苹果')
 
insert into Product values(2,'HP')
insert into Product values(2,'IBM')
insert into Product values(2,'Dell')
 
 
insert into Product values(3,'佳能')
insert into Product values(3,'尼康')
insert into Product values(3,'索尼')
go

看一下它们的数据

select 
from Category
left join Product on Category_ID = CategoryID

我们把它们用Group By分一下组

select Category_ID ,
Category_Name,
CategoryID,
Product_Name
from Category
left join Product on Category_ID = CategoryID
group by Category_ID ,CategoryID,Category_Name,Product_Name

我们看到这样和没有分组时展现的数据是一样的,让我们加上 ROLLUP 加上合计行

select Category_ID ,               
        Category_Name,     
        CategoryID,    
        Product_Name   
from Category
left join Product on Category_ID = CategoryID
group by Category_ID ,CategoryID,Category_Name,Product_Name  with rollup

我们看到了好多NULL数据,而且很有规律

这些规律我们可以用Grouping 看到

select Category_ID ,
        GROUPING(Category_ID) as Category_IDGP,                    
        Category_Name,
        GROUPING(Category_Name) as Category_NameGP,    
        CategoryID,
        GROUPING(CategoryID) as CategoryIDGP,      
        Product_Name,
        GROUPING(Product_Name) as Product_NameGP
from Category
left join Product on Category_ID = CategoryID
group by Category_ID ,Category_Name,CategoryID,Product_Name with rollup

你会发现那些Null值就是Grouping 为1的时候

最后一行的合计是Categrory_ID的,我们不需要,CategoryID的合计我们也不需要我们要怎么去掉它们呢,在having 里

select Category_ID ,
        GROUPING(Category_ID) as Category_IDGP,    
        CategoryID,
        GROUPING(CategoryID) as CategoryIDGP,      
        Category_Name,
        GROUPING(Category_Name) as Category_NameGP,
        Product_Name,
        GROUPING(Product_Name) as Product_NameGP
from Category
left join Product on Category_ID = CategoryID
group by Category_ID ,Category_Name,CategoryID,Product_Name with rollup
having GROUPING(Category_ID)=0  and GROUPING(CategoryID)=0

这样的结果 我们看到只有Product_Name的Grouping有为1 了

我们就是用它去实现这棵树

select
case GROUPING(Product_Name) when 1 then Category_Name  else '' end as Category_Name,
case GROUPING(Product_Name) when 0 then Product_Name else '' end as Product_Name
from Category
left join Product on Category_ID = CategoryID
group by Category_ID ,Category_Name,CategoryID,Product_Name with rollup
having GROUPING(Category_ID)=0  and GROUPING(CategoryID)=0
order by Category_ID ,Product_Name

下面是完整的代码

use master 
go
if exists(select 1 from sysdatabases where name ='MyGroupDB')
    ALTER DATABASE MyGroupDB SET SINGLE_USER with ROLLBACK IMMEDIATE 
    drop database MyGroupDB
go
 
create database MyGroupDB
go
use MyGroupDB
go
 
create Table Category
(
    Category_ID int identity(1,1),
    Category_Name varchar(100)
)
go
create Table Product
(
    Product_ID int identity(1,1),
    CategoryID int ,
    Product_Name varchar(100)
)
go
insert into Category values('手机')
insert into Category values('台式机')
insert into Category values('数码相机')
go
 
insert into Product values(1,'诺基亚')
insert into Product values(1,'三星')
insert into Product values(1,'苹果')
 
insert into Product values(2,'HP')
insert into Product values(2,'IBM')
insert into Product values(2,'Dell')
 
 
insert into Product values(3,'佳能')
insert into Product values(3,'尼康')
insert into Product values(3,'索尼')
go
 
 
select 
from Category
left join Product on Category_ID = CategoryID
--------------------------------------------------------
 
select Category_ID ,               
        Category_Name,     
        CategoryID,    
        Product_Name   
from Category
left join Product on Category_ID = CategoryID
group by Category_ID ,CategoryID,Category_Name,Product_Name  with rollup
 
--------------------------------------------------------
select Category_ID ,
        GROUPING(Category_ID) as Category_IDGP,                    
        Category_Name,
        GROUPING(Category_Name) as Category_NameGP,    
        CategoryID,
        GROUPING(CategoryID) as CategoryIDGP,      
        Product_Name,
        GROUPING(Product_Name) as Product_NameGP
from Category
left join Product on Category_ID = CategoryID
group by Category_ID ,Category_Name,CategoryID,Product_Name with rollup
 
----------------------
select Category_ID ,
        GROUPING(Category_ID) as Category_IDGP,    
        CategoryID,
        GROUPING(CategoryID) as CategoryIDGP,      
        Category_Name,
        GROUPING(Category_Name) as Category_NameGP,
        Product_Name,
        GROUPING(Product_Name) as Product_NameGP
from Category
left join Product on Category_ID = CategoryID
group by Category_ID ,Category_Name,CategoryID,Product_Name with rollup
having GROUPING(Category_ID)=0  and GROUPING(CategoryID)=0
 
-------------------------
 
select
case GROUPING(Product_Name) when 1 then Category_Name  else '' end as Category_Name,
case GROUPING(Product_Name) when 0 then Product_Name else '' end as Product_Name
from Category
left join Product on Category_ID = CategoryID
group by Category_ID ,Category_Name,CategoryID,Product_Name with rollup
having GROUPING(Category_ID)=0  and GROUPING(CategoryID)=0
order by Category_ID ,Product_Name

  

Group by Grouping的更多相关文章

  1. 玩转数据库之 Group by Grouping

    有的时候我们要从数据库里把数据组织成树结构再展现到页面上 像下面这样 今天我们用Group 和Grouping实现它,并总结一下它俩. 先看一下概念,再用代码一点一点去理解它们,最后我会给出完整的代码 ...

  2. Group By Grouping Sets

    Group by分组函数的自定义,与group by配合使用可更加灵活的对结果集进行分组,Grouping sets会对各个层级进行汇总,然后将各个层级的汇总值union all在一起,但却比单纯的g ...

  3. Oracle PL/SQL之GROUP BY GROUPING SETS

    [转自] http://blog.csdn.net/t0nsha/article/details/6538838 使用GROUP BY GROUPING SETS相当于把需要GROUP的集合用UNIO ...

  4. GROUP BY GROUPING SETS 示例

    --建表 create table TEst1 ( ID ), co_CODE ), T_NAME ), Money INTEGER, P_code ) ); --插入基础数据 insert into ...

  5. group by <grouping sets(...) ><cube(...)>

    GROUP BY      GROUPING SETS() 后面将还会写学习 with cube,  with rollup,以及将它们转换为标准的GROUP BY的子句GROUP SET(), CU ...

  6. SQL GROUP BY GROUPING SETS,ROLLUP,CUBE(需求举例)

    实现按照不同级别分组统计 关于GROUP BY 中的GROUPING SETS,ROLLUP,CUBE 从需求的角度理解会更加容易些. 需求举例: 假如一所学校只有两个系, 每个系有两个专业, 每个专 ...

  7. (4.6)sql2008中的group by grouping sets

    最近遇到一个情况,需要在内网系统中出一个统计报表.需要根据不同条件使用多个group by语句.需要将所有聚合的数据进行UNION操作来完成不同维度的统计查看. 直到发现在SQL SERVER 200 ...

  8. SQL Server 之 GROUP BY、GROUPING SETS、ROLLUP、CUBE

    1.创建表 Staff CREATE TABLE [dbo].[Staff]( ,) NOT NULL, ) NULL, ) NULL, ) NULL, [Money] [int] NULL, [Cr ...

  9. [Oracle] Group By 语句的扩展 - Rollup、Cube和Grouping Sets

    常常写SQL语句的人应该知道Group by语句的主要使用方法是进行分类汇总,以下是一种它最常见的使用方法(依据部门.职位分别统计业绩): SELECT a.dname,b.job,SUM(b.sal ...

随机推荐

  1. Angularjs -- 核心概念

     angularjs旨在减轻使用AJAX开发应用程序的复杂度,使得程序的创建.測试.扩展和维护变得easy.以下是angularjs中的一些核心概念. 1. client模板      多页面的应用通 ...

  2. Android SDK 2.2 离线安装

    android的普通安装方法非常easy,不必多说. 因为普通安装方法速度非常慢,对一般的用户要数小时的时间等待. 为更高速安装,能够採取离线安装方法.即,先分别下载所需包,再安装. 一,首先下载SD ...

  3. Angular指令(一)

    Angular开发者手册重点翻译之指令(一) 创建自定义的指令 这个文章将解释什么需要在自己的angularjs应用中创建自己的指令,以及如何实现它. 什么是指令 在高的层面上讲,指令是DOM元素中的 ...

  4. 学习的例子gcc+gdb+make

    1 小侃GCC 在正式使用gcc之前,我们先来侃侃gcc是啥玩意儿? 历史 如今的GCC是GNU Compiler Collection的简称.既然是Collection,就是指一些工具链的集合. 最 ...

  5. Virtualbox之Ubuntu虚拟机网络访问设置

    在本机(Win7)中 利用VirtualBox安装了一个Ubuntu虚拟机,由于使用桥接,所以本机和虚拟机处于同一个网络局域网下,,主机能访问虚拟机.可是在Ubuntu更新软件的时候才发现不能联网.首 ...

  6. C# 编译器选项 /platform(指定输出平台)32位程序运行到x64平台的问题

    如果说你编译的exe运行时报错: “尝试读取或写入受保护的内存.这通常指示其他内存已损坏” 这很有可能是你是以非托管的方式错误地引用了64位的API中去. 为什么会这样? 那你就要考虑VS的编译器选项 ...

  7. Objective-C和Swift

    在项目中同时使用Objective-C和Swift 苹果发布的Swift语言可以和之前的Objective-C语言同时存在于一个项目中. 可能有人会认为是同一个类文件中既可以有Objective-C也 ...

  8. Rich IntelliSense for jQuery

    A while back we updated VS2008 IntelliSense to not fail when referencing jQuery.  However, getting I ...

  9. Lucene.net入门学习

    Lucene.net入门学习(结合盘古分词)   Lucene简介 Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全 ...

  10. Android学习路径(四)文件项目学习的名单,android显示单元经常使用的

    1.的该项目文件所谓名单AndroidManifest.xml文件.该文件,但有很大的利用,例:app名字.图标,app支持的版本app等等.以下我就介绍下这个清单文件的各个參数的作用. <ma ...