玩轉數據庫之 Group by Grouping

有的時候咱們要從數據庫裏把數據組織成樹結構再展示到頁面上sql

像下面這樣數據庫

今天咱們用Group 和Grouping實現它,並總結一下它倆。ide

先看一下概念,再用代碼一點一點去理解它們,最後我會給出完整的代碼函數

Group By : 語句用於結合合計函數,根據一個或多個列對結果集進行分組。ui

Grouping :指示是否聚合 GROUP BY 列表中的指定列表達式。 在結果集中,若是 GROUPING 返回 1 則指示聚合;spa

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

ROLLUP :生成簡單的 GROUP BY 聚合行以及小計行或超聚合行,還生成一個總計行。code

讓咱們先建一個數據庫,並添加一些數據blog

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

看一下它們的數據ci

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
相關文章
相關標籤/搜索