sql根据团队树一级一级汇总统计
1、需求描述
最近碰到了一个需求,是要统计各个团队的员工的销售金额,然后一级一级向上汇总。

编辑
架构团队树是类似于这种样子的,需要先算出每个员工的销售金额,然后汇总成上一级的团队金额,然后各个团队的销售总金额再往上汇总成一个区域的销售金额,然后各个区域的金额再往上汇总成总公司的金额。当然我工作碰到的团队树要远比这个复杂许多,但反正差不多是这么个意思。
2、解决方法
2.1、方法一(不推荐)
持久层通过一些sql把团队树结构,以及各个员工的销售金额汇总拿到,然后在业务层通过代码去一层层拼起来。这是我一开始拿到这个需求时的思路,后来发现可以但是很复杂,代码可读性及可维护性很差。
2.2、方法二(推荐)
在sql里面计算汇总出来。
我这里是在测试环境建了几张Demo表来加以说明sql的逻辑。
1、建表、
CREATE TABLE Business..TGroupV2(TreeNodeNo int,TeamId int,TeamName varchar(100),[Path] varchar(100));
CREATE TABLE Business..TPeopleSalesInfoV2(TeamId int,PeopleId varchar(100),PeopleName varchar(100));
CREATE TABLE Business..TPeopleSalesDetailInfoV2(PeopleId varchar(100),Amount Decimal(18,2),ContractID varchar(100));

2、添加一些测试数据

编辑
3、SQL代码
--以团队为单位,汇总各个团队,子团队,父团队的销售金额
SELECT TB.TreeNodeNo,TB.TeamID,TB.TeamName,AA.Amount,'' as PeopleId ,'' as PeopleName FROM
(
SELECT A.ParentTeamID,SUM(A.Amount) as Amount FROM
(
SELECT
TT.*,TG2.TeamID as ParentTeamID,BB.Amount from
(
select T1.*,TG.[Path]
from Business..TPeopleSalesInfoV2 T1
left join Business..TGroupV2 TG on T1.TeamId=TG.TeamId
) AS TT
left join Business..TGroupV2 TG1 on TT.TeamId=TG1.TeamId
left join Business..TGroupV2 TG2 on
TG1.[Path] LIKE ('%\' + convert(varchar(50),TG2.TeamID))
or TG1.[Path] like ('%\' + convert(varchar(100),TG2.TeamID) + '\%')
or TG1.[Path] like (convert(varchar(50),TG2.TeamID) + '\%')
or TG1.[Path] = convert(varchar(50),TG2.TeamID)
LEFT JOIN
(select PeopleId,SUM(Amount) as Amount from Business..TPeopleSalesDetailInfoV2 group by PeopleId)
as BB on TT.PeopleId=BB.PeopleId
) A GROUP by ParentTeamID
) as AA LEFT JOIN Business..TGroupV2 TB on TB.TeamID=AA.ParentTeamID
UNION
--以员工为单位获取各个销售人员的销售金额
select TB.TreeNodeNo,TB.TeamID,TB.TeamName,SUM(TP.Amount) as Amount,TP.PeopleId,TPS.PeopleName from Business..TPeopleSalesDetailInfoV2 TP
LEFT JOIN Business..TPeopleSalesInfoV2 TPS on TPS.PeopleId=TP.PeopleId
LEFT JOIN Business..TGroupV2 TB on TB.TeamID=TPS.TeamID
group by TB.TreeNodeNo,TB.TeamID,TB.TeamName,TP.PeopleId,TPS.PeopleName
ORDER BY TreeNodeNo,PeopleId ASC


编辑
2.3、思路说明

编辑
3、总结
随着数据量增加一些老的sql查询性能太慢了,经常出现这种查询超时问题。

编辑
造成这种问题的原因有很多,一种是sql写的太烂了,业务层有循环查询。就像我方法一中的那种思想,不可避免你要循环查询出每个团队的金额再一级一级向上汇总。还有就是不合理的权限控制。比如你要查询团队的销售金额。因为团队的关系是一个树状结构嘛。假如你是东区的领导,你只能查询东区及其下所有子团队的数据,但在权限判断这块,其实是会东区下每个子团队,以及子团队的子团队.....都要判断一遍你有没有查询的权限。这样就增加了不必要的负担。不过这个是历史遗留问题,是因为之前的权限结构设计就不完善,也不太好改。
解决方法嘛,目前我就是通过存储过程取代select查询,因为存储过程是预编译的,所以执行起来开销比较小所以速度比较快。可以看下这篇详细了解下:为什么存储过程比sql语句效率高? - herizai - 博客园 (cnblogs.com)
因为原先的select查询关联了好多表以及视图,各种join的,可读性很差。我所要做的就是理清这些join之间的关系, 存储过程中用几个临时表把大的join拆成合并成小的join。再加一些注释什么的,虽然业务没有变,只是代码更容易理解了。速度确实快了一些,不在出现查询的超时的问题了。
4、参考资料
为什么要用存储过程,存储过程的优缺点。。_jokeylin的博客-CSDN博客
为什么存储过程比sql语句效率高? - herizai - 博客园 (cnblogs.com)
sql根据团队树一级一级汇总统计的更多相关文章
- SQL基础-汇总统计及GROUP BY
一.汇总统计 1.聚集函数 COUNT() 计算总数 SUM() 求和 MAX() 最大值 MIN() 最小值 AVG() 平均值 2.聚集函数使用 总共有多少名学生? SELECT COUNT(*) ...
- SQL SERVER 月、季、年统计与常用查询语句汇总
一.SQL SERVER 月.季.年统计查询 --本天 SELECT *FROM dbo.TableName WHERE DATEDIFF(DAY,TimeField,getdate())= 0; - ...
- 每日学习心得:SQL查询表的行列转换/小计/统计(with rollup,with cube,pivot解析)
2013-8-20 1. SQL查询表的行列转换/小计/统计(with rollup,with cube,pivot解析) 在实际的项目开发中有很多项目都会有报表模块,今天就通过一个小的SQL ...
- oracle pipelined返回值函数 针对数据汇总统计 返回结果集方法
近期需要一个汇总统计,由于数据太多,数据量太大所以在java程序中实现比较困难.若用后台程序统计,数据不能保证实时,同时实现周期比较长.顾使用函数返回结果集的方式,在不增加临时表的情况下实时获取数据. ...
- SQL查询表的行列转换/小计/统计(with rollup,with cube,pivot解析)
SQL查询表的行列转换/小计/统计(with rollup,with cube,pivot解析) 2013-8-20 1. SQL查询表的行列转换/小计/统计(with rollup,with ...
- 你真的会玩SQL吗?实用函数方法汇总
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- 64位 SQL Server2008链接访问Oracle 过程汇总解决方法记录
64位 SQL Server2008链接访问Oracle 过程汇总解决方法记录 经过几天不停的网上找资料,实验,终于联通了. 环境:系统:win 2008 ,SqlServer2008 R2, 连接O ...
- AspxGridView 数据的汇总统计
AspxGridView底部增加数据汇总行 这个功能在AspxGridView中不用复杂的代码实现, 实际上只是设置下GridView的属性而已 1. ShowFooter设置为True,即显示. 位 ...
- 国内顶尖的sql dba 团队招人。
国内顶尖的sql dba 团队招人. 4年DBA 经验 我们希望你掌握 1.熟练关系型数据库原理.熟练一门语言(C# .Java.Python.powershell ) 2.对自动化.数据化感兴趣. ...
- 如何用C#对Gridview的项目进行汇总统计?
上一次用了javascript对gridview进行了汇总统计,但那个统计是在客户端进行的,虽然减轻了服务器的负担,但是,当需要把统计信息汇出excel时,汇总信息却死活不出来了,所以,绕半天又绕回来 ...
随机推荐
- 【软件学习】怎么在Word里面设置MathType分隔符,使公式按照章节自动编号
前提 确保已安装好了MathType,且在设置为Word加载项 若没有安装或设置为加载项,请转至博客另一篇文章: [软件学习]如何下载安装Mathtype,并将其加载至Word 第一步 点击MathT ...
- SpringBoot(三) - Slf4j+logback 日志,异步请求,定时任务
1.Slf4j+logback 日志 SpringBoot框架的默认日志实现:slf4j + logback: 默认日志级别:info,对应了实际生产环境日志级别: 1.1 日志级别 # 常见的日志框 ...
- 从0搭建vue3组件库:Shake抖动组件
先看下效果 其实就是个抖动效果组件,实现起来也非常简单.之所以做这样一个组件是为了后面写Form表单的时候会用到它做一个规则校验,比如下面一个简单的登录页面,当点击登录会提示用户哪个信息没输入,当然这 ...
- 刷完一千道java笔试题的常见题目分析
java基础刷题遇到的最常见问题 可以先看一下这位博主整理的java面试题(很详细,我看了好几遍了):https://blog.csdn.net/ThinkWon/article/details/10 ...
- 齐博x1.3通用栏目名称及参数调用接口
对于全站的频道可以使用下面的方法取出相应的栏目名称及参数http://qb.net/index.php/cms/wxapp.sorts.html注意,只需要把qb.net换成你的域名,cms 换成其它 ...
- 齐博x1.1用户登录接口
用户的登录主要涉及到小程序登录.APP的帐号密码登录.APP的微信开发平台帐号登录.相应的地址是:http://qb.net/index.php/index/wxapp.login/index.htm ...
- 1、在SrpingBoot的环境当中使用JSP及相关功能
创建webapp目录 由于SpringBoot项目不建议直接访问jsp页面,但是我现在要做的事情需要去访问,那么我就需要在原有的项目基础上为访问jsp页面进行一个调整 首先在项目当中,java和res ...
- DevOps|1024程序员节怎么做?介绍下我的思路
1024,祝每个程序员小哥哥小姐姐节日快乐. 因为在研发效能部门,我支持过几次 1024 程序员节的活动,所以经常有朋友问我1024 程序员节怎么做,本篇就是简单介绍下我的思路,希望对你有用. 102 ...
- Debian11管理员手册
1 用户与群组数据库 用户清单通常保存在 /etc/passwd 文件内,把哈希编码后的密码保存在 /etc/shadow 文件内.这两个文件都是纯文本档,以简单的格式保存,可以用文本编辑器读取与修改 ...
- Java Stream流的使用
流相关的方法可以分为三种类型,分别是:获取Stream流.中间方法.终结方法.中间方法会返回当前流,可以方便的进行链式调用. 流不可重复使用,否则会报错: java.lang.IllegalState ...