MS SQL 分类汇总参数 grouping(**)=1 rollup cubt
转:http://www.111cn.net/database/mssqlserver/43368.htm
本文章介绍了关于sql多级分类汇总实现方法及数据结构,有碰到问题的同学可参考一下。
据库结构如下
类别表
分类id 上级分类id 分类名称 分类级别 排序值
代码如下 复制代码
id parentid categoryname categorylevel ordering
1 null c1 1 1
2 1 c11 2 1
3 1 c12 2 2
4 1 c13 2 3
5 1 c14 2 4
6 2 c111 3 1
7 2 c112 3 2
然后 内容表是
内容id 类别id .........
代码如下 复制代码
id categoryid .........
1 1 ........
2 4 ........
3 5 ........ 这样处理的弊端是:如果数据量大,子分类很多,达到4级以上,这方法处理极端占用数据库连接池
对性能影响很大。
如果用SQL下面的CTE递归处理的话,一次性就能把结果给查询出来,而且性能很不错
比用程序处理(数据量很大的情况),临时表性能更好,更方便
代码如下 复制代码
with area as(
select *,id px,cast(id as nvarchar(4000)) px2 from region where parentid=0
union all
select a.*,b.px,b.px2+ltrim(a.region_id) from region a join area b on a.parentid=b.id
)select * from area order by px,px2 可以查询出结果—-所有分类及相应分类下子分类
代码如下 复制代码
id title parentid
1 广东省 0
2 广州 1
3 白云区 2
4 深圳 1
5 湖南省 0
6 长沙 5
7 株洲 5
代码如下 复制代码 with area as(
select * from region where parentid=1
union all
select a.* from region a join area b on a.parentid=b.id
)select * from area
可以查询出结果—-指定分类及相应分类下子分类
id title parentid
1 广东省 0
2 广州 1
3 白云区 2 实现程序
代码如下 复制代码
/*
标题:查询指定节点及其所有子节点的函数
作者:爱新觉罗.毓华(十八年风雨,守得冰山雪莲花开)
时间:2008-05-12
地点:广东深圳
*/
create table tb(id varchar(3) , pid varchar(3) , name varchar(10))
insert into tb values('' , null , '广东省')
insert into tb values('' , '' , '广州市')
insert into tb values('' , '' , '深圳市')
insert into tb values('' , '' , '天河区')
insert into tb values('' , '' , '罗湖区')
insert into tb values('' , '' , '福田区')
insert into tb values('' , '' , '宝安区')
insert into tb values('' , '' , '西乡镇')
insert into tb values('' , '' , '龙华镇')
insert into tb values('' , '' , '松岗镇')
go
--查询指定节点及其所有子节点的函数
create function f_cid(@ID varchar(3)) returns @t_level table(id varchar(3) , level int)
as
begin
declare @level int
set @level = 1
insert into @t_level select @id , @level
while @@ROWCOUNT > 0
begin
set @level = @level + 1
insert into @t_level select a.id , @level
from tb a , @t_Level b
where a.pid = b.id and b.level = @level - 1
end
return
end
go
--调用函数查询001(广东省)及其所有子节点
select a.* from tb a , f_cid('') b where a.id = b.id order by a.id
/*
id pid name
---- ---- ----------
001 NULL 广东省
002 001 广州市
003 001 深圳市
004 002 天河区
005 003 罗湖区
006 003 福田区
007 003 宝安区
008 007 西乡镇
009 007 龙华镇
010 007 松岗镇
(所影响的行数为 10 行)
*/
--调用函数查询002(广州市)及其所有子节点
select a.* from tb a , f_cid('') b where a.id = b.id order by a.id
/*
id pid name
---- ---- ----------
002 001 广州市
004 002 天河区
(所影响的行数为 2 行)
*/
--调用函数查询003(深圳市)及其所有子节点
select a.* from tb a , f_cid('') b where a.id = b.id order by a.id
/*
id pid name
---- ---- ----------
003 001 深圳市
005 003 罗湖区
006 003 福田区
007 003 宝安区
008 007 西乡镇
009 007 龙华镇
010 007 松岗镇
(所影响的行数为 7 行)
*/
drop table tb
drop function f_cid 实例2 代码如下 复制代码
t1
id parentid
m a
n a
e m
f m
x f
y f
z b
t2
row id amount
1 a 13.00
2 b 20.00
3 e 20.00
4 f 20.00
5 x 20.00
6 y 20.00
7 z 20.00
8 e 12.00
9 x 11.00
10 f 13.00
如何得出如下结果:
row id amount
7 x 20.00
11 x 11.00
x小计 31.00
8 y 20.00
y小计 20.00
6 f 20.00
12 f 13.00
f小计 84.00
5 e 20.00
10 e 12.00
e小计 32.00
3 m 14.00
m小计 130.00
4 n 13.00
n小计 13.00
1 a 13.00
a小计 156.00
9 z 20.00
z小计 20.00
2 b 20.00
b小计 40.00
总计 196.00
实现程序
-- 示例数据
CREATE TABLE t1(
id char(1),
parentid char(1)
);
INSERT t1
SELECT 'm', 'a' UNION ALL
SELECT 'n', 'a' UNION ALL
SELECT 'e', 'm' UNION ALL
SELECT 'f', 'm' UNION ALL
SELECT 'x', 'f' UNION ALL
SELECT 'y', 'f' UNION ALL
SELECT 'z', 'b'; CREATE TABLE t2(
row int,
id char(1),
amount decimal(10, 2)
);
INSERT t2
SELECT '', 'a', '13.00' UNION ALL
SELECT '', 'b', '20.00' UNION ALL
SELECT '', 'e', '20.00' UNION ALL
SELECT '', 'f', '20.00' UNION ALL
SELECT '', 'x', '20.00' UNION ALL
SELECT '', 'y', '20.00' UNION ALL
SELECT '', 'z', '20.00' UNION ALL
SELECT '', 'e', '12.00' UNION ALL
SELECT '', 'x', '11.00' UNION ALL
SELECT '', 'f', '13.00';
GO -- 统计
-- 逐级汇总
declare @l int
set @l=1 select
A.[id],
[pid] = A.parentid,
[sumnum] = SUM(B.amount),
level=case
when exists(select * from t1 where parentid=a.[id])
then @l-1 else @l end
into [#]
from t1 A
LEFT JOIN t2 B
ON A.id = B.id
GROUP BY A.id, A.parentid; if @@rowsqlserver/42852.htm target=_blank >count>0
create index IDX_#_id_pid on [#]([id],[pid])
else
set @l=999 while @@rowcount>0 or @l=1
begin
set @l=@l+1
update a set level=@l,[sumnum]=isnull(a.[sumnum],0)+isnull(b.[sumnum],0)
from [#] a,(
select aa.pid,[sumnum]=sum(aa.[sumnum])
from [#] aa,(
select distinct [pid] from [#]
where level=@l-1
)bb where aa.[pid]=bb.[pid]
AND NOT EXISTS(
SELECT * FROM [#] WHERE [PID]=aa.[PID] AND [Level]=0)
GROUP BY aa.[PID]
having sum(case when aa.level=0 then 1 else 0 end)=0
)b where a.[id]=b.[pid]
end -- 最终结果
SELECT
row = CASE
WHEN GROUPING(A.row) = 0 THEN RTRIM(A.row)
ELSE N''
END,
id = CASE
WHEN GROUPING(A.row) = 0 THEN A.id
WHEN GROUPING(A.id) = 0 THEN A.id + '小计'
ELSE N'总计'
END,
amount = CASE
WHEN GROUPING(A.row) = 0 THEN SUM(A.amount)
WHEN GROUPING(A.id) = 0 THEN ISNULL((SELECT SUM(B.sumnum) FROM # B WHERE A.id = B.id), SUM(A.amount))
ELSE SUM(A.amount)
END
FROM t2 A
GROUP BY A.id, A.row WITH ROLLUP;
drop table [#]
GO DROP TABLE t1, t2; /*-- 结果
row id amount
------------ ----- ---------------------------------------
1 a 13.00
a小计 13.00
2 b 20.00
b小计 20.00
3 e 20.00
8 e 12.00
e小计 32.00
4 f 20.00
10 f 13.00
f小计 84.00
5 x 20.00
9 x 11.00
x小计 31.00
6 y 20.00
y小计 20.00
7 z 20.00
z小计 20.00
总计 169.00 (18 行受影响)
--*/
MS SQL 分类汇总参数 grouping(**)=1 rollup cubt的更多相关文章
- (2.4)DDL增强功能-数据汇总grouping、rollup、cube
参考:https://www.cnblogs.com/nikyxxx/archive/2012/11/27/2791001.html 1.rollup (1)rollup在group by 子句中使用 ...
- SQL之按两个字段分类汇总
目的: 同时按"游戏代号"和"礼包名"分类汇总,然后获取下拉框的数据. 如下图所示: SQL查询 select game,giftname from qyg_ ...
- SQL GROUP BY GROUPING SETS,ROLLUP,CUBE(需求举例)
实现按照不同级别分组统计 关于GROUP BY 中的GROUPING SETS,ROLLUP,CUBE 从需求的角度理解会更加容易些. 需求举例: 假如一所学校只有两个系, 每个系有两个专业, 每个专 ...
- SQL Server case when 实现分类汇总
case when 实现分类汇总
- MariaDB——SQL语句分类汇总
常用SQL语句汇总 SQL语句在所有的关系型数据库中都是通用的,算起来sql语句也是一门语言,只不过这门语言的主要操作对象是关系型的数据库,其中最常用的还是查询相关的语句. sql语句主要分为: DQ ...
- MS SQL优化
数据库优化实践[MS SQL优化开篇] 数据库定义: 数据库是依照某种数据模型组织起来并存在二级存储器中的数据集合,此集合具有尽可能不重复,以最优方式为特定组织提供多种应用服务,其数据结构独立于应 ...
- MS SQL 日志记录管理
MS SQL的日志信息/日志记录,可能对你来说,既熟悉又陌生,熟悉是因为你可能一直都在使用,查看.关注一些日志信息/记录,例如,作业历史记录:陌生是因为你可能从不关注日志信息/记录的管理,这里我一直用 ...
- MS SQL 字符拆分存处理
MS SQL Server没有split()函数,但是我们可以写一个Table-valued Functions定义函数[dbo].[udf_SplitStringToTable] : CREATE ...
- 在易语言中调用MS SQL SERVER数据库存储过程方法总结
Microsoft SQL SERVER 数据库存储过程,根据其输入输出数据,笼统的可以分为以下几种情况或其组合:无输入,有一个或多个输入参数,无输出,直接返回(return)一个值,通过output ...
随机推荐
- Ubuntu 16.04将系统时间写入到硬件时间BIOS
说明:在Ubuntu中为了和Windows保持一致,会将系统时间设置成CST的,所以下面的说法是设置成UTC的问题是由于所在的环境不一致导致的,本章只讨论如何设置时间到BIOS,不做时区分析,下面忽略 ...
- 大白话5分钟带你走进人工智能-第二十节逻辑回归和Softmax多分类问题(5)
大白话5分钟带你走进人工智能-第二十节逻辑回归和Softmax多分类问题(5) 上一节中,我们讲 ...
- UBI文件系统简介
转:http://www.embedu.org/Column/Column102.htm 在linux-2.6.27以前,谈到Flash文件系统,大家很多时候多会想到cramfs.jffs2.yaff ...
- 如何把自己的代码发布到npmjs(npm publish)
来源: https://www.cnblogs.com/calamus/p/8384318.html
- Java:网络编程之应用实例
1.聊天 编写一个聊天程序,有收数据的部分和发数据的部分. 这两部分需要同时执行,那么就需要多线程技术. 一个线程控制发送. 一个线程控制接收. 因为收和发动作是不一致的,所以要定义两个run方法,而 ...
- selenium firefox设置代理
from selenium import webdriver profile = webdriver.FirefoxProfile() profile.set_preference('network. ...
- IP头,TCP头,UDP头,MAC帧头定义
一.MAC帧头定义 /*数据帧定义,头14个字节,尾4个字节*/ typedef struct _MAC_FRAME_HEADER { char m_cDstMacAddress[6]; // ...
- Section Formula
https://brilliant.org/wiki/section-formula/
- [Angular] Debug Angular apps in production without revealing source maps
Source: https://blog.angularindepth.com/debug-angular-apps-in-production-without-revealing-source-ma ...
- iOS开发 最近开发了蓝牙模块,在此记录总结一下(转载)
1.基本概念 <1>中心者模式:常用的(其实99.99%)就是使用中心者模式作为开发,就是我们手机作为主机,连接蓝牙外设.由于开发只用到了中心者模式,所以我也只介绍中心者模式. <2 ...