玩轉數據庫之 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

  

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM