SQLServer---使用Case When解决SQLServer数据分类汇总问题
近半年一直在负责某市的人事档案管理系统的后期开发和维护工作,之前客户给了一张如下图的表格,需要我去汇总数据,然后填充到表格中。
具体的需求:统计出每一个工作人员在某一段时间内分别打印了多少张不同的信函(或报表)。
最初的想法
1、 查出使用该系统的工作人员
select realName as '姓名' from T_User
where
userID in(select distinct userID from T_OperationLog);
运行结果:
2、 分别查出不同员工打印的不同信函的数量(下面以干部介绍信为例)
select realName as '姓名', COUNT(*) as '干部介绍信' from T_LettersRecord as l,T_User as u
where
l.userID=u.userID and letterType = '干部介绍信' and l.userID in(select distinct userID from T_OperationLog)
group by l.userID,u.realName;
运行结果:
但是这个时候有一个问题我们统计一种类型的信函的时候COUNT(*)就行了,但是当我们我们要统计其他信函的时候我们该怎么使用COUNT函数呢?与此同时letterType(信函类型)作为一个条件也是不同的。
作为一个菜鸟我最先想到的不是SqlServer中一大堆你牛逼的函数而是想先用一个类似于数组的东西将letterType都存进去,在SQLServer中不支持数据于是我用了变量表去实现类似的功能。
--声明一个表变量
declare @t table (id int,name varchar(20))
insert into @t values(1,'干部介绍信')
insert into @t values(2,'存档证明信')
select realName as '姓名' ,count(*)
from T_LettersRecord as l,T_User as u
where l.userID=u.userID and letterType in(select name from @t) and l.userID in(select distinct userID
from T_OperationLog) group by l.userID,u.realName,letterType
运行结果:
从运行结果中我们可以看出,最终的结果是竖排的并不是我想要的横排效果,于是问题就又出来了如何让它有横排的效果。我想到了用左连接(left join … on),将每次查出的结果都存到一个临时表中,然后将将这些临时表依次用left join … on最终得出我想要的结果。
实际的做法
上面的那个想法在我想出的那一瞬间就被我否定了,这样又是循环,又是连接查询效率就会很慢而且后来的人维护起来也比较麻烦。在同事的提醒下,我使用了case when解决了这个问题。
最终代码如下:
select realName as '姓名',
COUNT(case when letterType='干部介绍信' then '1' end) as '干部介绍信',
COUNT(case when letterType='转递档案通知单' then '1' end)as '转档通知单',
.
.
.
COUNT(case when letterType='职称审批表' then '1' end) as '职称审批表',
COUNT(case when letterType='党员信息表' then '1' end) as '党员信息表',
COUNT(case when letterType='其他' then '1' end) as '其他'
from T_LettersRecord as l,T_User as u
where l.userID=u.userID and l.userID in(select distinct userID
from T_OperationLog) group by l.userID,u.realName;
最终的运行结果:
完全的符合用户最终的要求。在写这段代码之前也问过旁边的一个同事,她的第一反应就是不会,这样的结果就是她真的不会了,其实要是想任务分解就像我最初的想法那样也是能够写出了,写出来之后优化肯定又是另一种感觉了(遇到问题先尝试一下总是对的)。
下一篇博文会介绍一下case…when…的具体用法。