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 ...
随机推荐
- mysql系列-安装及服务启动
一.window下的安装 详细见官网 https://dev.mysql.com/doc/refman/5.7/en/windows-installation.html 以 MySQL 5.1 免安装 ...
- [sharepoint]文档库,文件夹授权
写在前面 在项目中用到了文档库授权的方法,这里将查询到的方式总结一下. 涉及到的方法 在逻辑中用到的方法. /// <summary> /// 获取sharepoint站点角色定义 res ...
- sourceinsight----tabsiplus颜色配置文件
参考: http://blog.csdn.net/orbit/article/details/7585607 下面是我的颜色配置 http://files.cnblogs.com/pengdongli ...
- ASIHTTPRequest框架使用总结系列之阿堂教程5(上传数据)
在上篇文章中,阿堂和网友们分享了如何用ASIHTTPRequest框架下载数据的实例,本篇阿堂将数据介绍如何用ASIHTTPRequest框架上传数据的应用实例. 数据上传是通过ASIHT ...
- linux字符设备文件的打开操作
2.7 字符设备文件的打开操作(1) 作为例子,这里假定前面对应于/dev/demodev设备节点的驱动程序在自己的代码里实现了如下的struct file_operations对象fops: st ...
- linux /etc/hosts 配置问题
在java code中获取本机IP的程序如下: import java.net.InetAddress; public class Test { public static void main(Str ...
- ListView控件绑定DataSet
DataSet数据集,数据缓存在客户端内存中,支持断开式连接. 在对DataSet做操作的时候,首先一定要修改其行的状态,然后执行SqlDataAdapter的Update方法,Update方法根 ...
- Picasso自定义缓存目录
项目做完终于有点自己的时间了,就想看点源码涨涨姿势,那就看看Picasso这个牛逼哄哄的图片加载框架吧,当然这个也是自己最喜欢的图片加载框架. 实际项目中可能有需求自己定制图片的缓存目录,那么就需要自 ...
- IOS--苹果各地区开发者支援的电话号码
网页地址: https://developer.apple.com/contact/phone/ 中国区的咨询热线:4006 701 855 邓白氏申请中心的电话(400-6701855)
- 网络编程 TCP学习
上传txt文本 通过socket向服务端发送数据 然后用serversocket 接收socket 通过流读取数据保存 服务端在发送确认信息并在client输出 client import java. ...