玩转数据库之 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

  

本文转自lpxxn博客园博客,原文链接:http://www.cnblogs.com/li-peng/p/3298303.html,如需转载请自行联系原作者

相关文章
|
7月前
|
SQL 关系型数据库 MySQL
MySQL数据库——SQL优化(2/3)-order by 优化、group by 优化
MySQL数据库——SQL优化(2/3)-order by 优化、group by 优化
72 0
|
8月前
|
存储 SQL Apache
阿里云数据库内核 Apache Doris 基于 Workload Group 的负载隔离能力解读
阿里云数据库内核 Apache Doris 基于 Workload Group 的负载隔离能力解读
阿里云数据库内核 Apache Doris 基于 Workload Group 的负载隔离能力解读
|
8月前
|
数据库
sqlserver数据库学习感悟(1)----关于group by
sqlserver数据库学习感悟(1)----关于group by
59 0
|
数据库
达梦数据库,第二章:报错不是 GROUP BY 表达式
达梦数据库,第二章:报错不是 GROUP BY 表达式
520 0
达梦数据库,第二章:报错不是 GROUP BY 表达式
|
关系型数据库 MySQL 数据库
【黄啊码】MySQL入门—5、数据库小技巧:单个列group by就会,多个列呢?
【黄啊码】MySQL入门—5、数据库小技巧:单个列group by就会,多个列呢?
126 0
【黄啊码】MySQL入门—5、数据库小技巧:单个列group by就会,多个列呢?
|
Go 数据库
玩转数据库之 Group by Grouping
有的时候我们要从数据库里把数据组织成树结构再展现到页面上 像下面这样 今天我们用Group 和Grouping实现它,并总结一下它俩。 先看一下概念,再用代码一点一点去理解它们,最后我会给出完整的代码 Group By : 语句用于结合合计函数,根据一个或多个列对结果集进行分组。
1141 0
|
21天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
47 3
|
21天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
54 3
|
21天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE &#39;log_%&#39;;`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
72 2
|
1月前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
227 15