做个东西,发现了些问题,又解决了,很Happy!
数据库有2个表:
[省份表],2列(provinceId--省的id,provinceName--省名字),
[公司表],好几列(companyId--公司Id, provinceId--公司所在省id, recruitType--这个招聘会类型(只有1,2,3这三个值,每个值一个含义),......其他问题无关列)
------------------------------------------------------------------------------------------------
方法一:(自己写的)
------------------------------------------------------------------------------------------------
我想获得的结果,即每个省按那三个招聘会类型统计各种类型公司的总数,如下:
------------------------------------------------------------------------------------------------
先获得了下面表,省id,招聘会类型,公司总数,这是在[公司表]里面按(省id,招聘会类型)group by和count()得到的,注意这里有个问题,就是[公司表]里面不是什么省份的都有,所以provinceId是不连续的,所以要在后面处理.
------------------------------------------------------------------------------------------------
然后联合[省份表],得到下面的表,这个很容易,只要注意一下 left join,就可以显示所有的省份了
------------------------------------------------------------------------------------------------
现在问题来了,我想显示的目标图是第一个图,就是这么把那些相同省的行合并为同一行,并且有三个列分别显示那三种招聘会类型的公司总数?
我想了半天,因为最终是要在Web上显示的,我想要不就在数据库搞好,把结果直接返回,Web端就不要处理什么了,要不就这样返回吧,在Web端合并相同的行,
但最后发现还是数据库端好处理,因为T-SQL很强大,并且Web端处理这些表格很麻烦,我不知道它那些DataTable啊什么的类似怎么样构造的,遂选择在数据库端处理.
------------------------------------------------------------------------------------------------
1,建立最后想要结果的表,把目标列写好,然后要不insert,要不update
2,用游标一个一个处理上面的那个表,provinceId一样的就update那一行几个值,否则insert新行
3,最后处理一些数据,得到想要结果:
代码量大啊!!!主要用游标一行一行处理的......
USE [Statistics] GO /****** Object: StoredProcedure [dbo].[procAnalyseProvince] Script Date: 2013/12/11 16:22:25 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: <Author,,Name> -- Create date: <Create Date,,> -- Description: 按招聘单位地域统计的数据源 -- ============================================= ALTER PROCEDURE [dbo].[procAnalyseProvince] @timeFrom char(10), @timeTo char(20) AS BEGIN /*下面是第一部分,获得临时表: [provinceId,recruitType,companySum] ,注意这里的provinceId可能只有一部分,即来招聘的那部分*/ begin if OBJECT_ID(N'#tableTemp',N'U') is not null drop table #tableTemp end select [Companys].provinceId , [Companys].recruitType ,COUNT(*) as companySum into #tableTemp from [Companys] --到临时表-----------------------------表的列:[provinceId,recruitType,companySum] where [Companys].recruitTime between @timeFrom and @timeTo group by [Companys].provinceId,[Companys].recruitType --根据省份和招聘会类型分组,不管哪个是哪个团体 order by [Companys].provinceId /*下面也是一部分,获得临时表: [provinceId,provinceName,recruitType,companySum] ,注意这里的provinceId包含数据库中全部省*/ begin if OBJECT_ID(N'#newTable',N'U') is not null drop table #newTable end select [Provinces].provinceId,[Provinces].provinceName,#tableTemp.recruitType,#tableTemp.companySum into #newTable --到临时表----------------------------------表的列:[provinceId,provinceName,recruitType,companySum] from [Provinces] left join #tableTemp on [Provinces].provinceId=#tableTemp.provinceId order by [Provinces].provinceId ASC, #tableTemp.recruitType ASC /*下面作处理,先创建最后结果表:*/ begin if OBJECT_ID(N'#lastTable',N'U') is not null drop table #lastTable end create table #lastTable --创建表最终要返回应用程序的表!!!!注意这里的强大之处!!! ( provinceId int primary key, provinceName nvarchar(20) not null, type1Sum int default 0, --默认值为0,省去null处理的麻烦 type1Ratio varchar(10), type2Sum int default 0, type2Ratio varchar(10), type3Sum int default 0, type3Ratio varchar(10), allTypeSum int default 0, allTypeRatio varchar(10) ) /*下面用游标处理表,第一次处理,只是在最终表填了[provinceId,provinceName,type1Sum,type2Sum,type3Sum]*/ begin --这里定义一些变量 declare @preProvinceId int --上一个省的id set @preProvinceId=0 --初始为0 declare @provinceId int,@provinceName nvarchar(20),@recruitType int,@companySum int --定义一个游标所对应的一行值 end declare curToNewTable scroll cursor for select * from #newTable open curToNewTable fetch first from curToNewTable into @provinceId,@provinceName,@recruitType,@companySum --取第一条 while @@FETCH_STATUS=0 --取成功了 begin if(@provinceId!=@preProvinceId) --跟上一次的不一样,所以要插入新行 begin set @preProvinceId=@provinceId --先设置这个 if(@recruitType is null) --注意,这里因为之前的原因,@recruitType可能为null,这样这一行只录入省 insert into #lastTable (provinceId,provinceName) values (@provinceId,@provinceName) else if(@recruitType=1) insert into #lastTable (provinceId,provinceName,type1Sum) values(@provinceId,@provinceName,@companySum) else if(@recruitType=2) insert into #lastTable (provinceId,provinceName,type2Sum) values(@provinceId,@provinceName,@companySum) else --3,@recruitType只有null,1,2,3,这四种值 insert into #lastTable (provinceId,provinceName,type3Sum) values(@provinceId,@provinceName,@companySum) end else --一样,就update那一行 begin if(@recruitType=1) --这里就不要管@recruitType是null了,那不处理 update #lastTable set #lastTable.type1Sum=@companySum where #lastTable.provinceId=@provinceId else if(@recruitType=2) update #lastTable set #lastTable.type2Sum=@companySum where #lastTable.provinceId=@provinceId else if(@recruitType=3) update #lastTable set #lastTable.type3Sum=@companySum where #lastTable.provinceId=@provinceId end fetch next from curToNewTable into @provinceId,@provinceName,@recruitType,@companySum --取下一条 end close curToNewTable --关闭游标 deallocate curToNewTable --释放游标资源 /*下面用游标对最后结果表作第二次处理,即把表的全部项填满除了总计的比例项*/ declare @allSingleTotal int,@allMediumTotal int,@allBigTotal int,@allTypeTotal int --整体的,这几个值是放到最后一行"总计"的 set @allSingleTotal=(select sum(type1Sum) from #lastTable) set @allMediumTotal=(select sum(type2Sum) from #lastTable) set @allBigTotal=(select sum(type3Sum) from #lastTable) set @allTypeTotal=@allSingleTotal+@allMediumTotal+@allBigTotal --其实这个值也为这一列的所有值的和 declare @lineType1Sum int,@lineType2Sum int,@lineType3Sum int,@lineTypeAllSum int--一行的 declare curToFillRatio scroll cursor for select type1Sum,type2Sum,type3Sum from #lastTable --游标 open curToFillRatio fetch first from curToFillRatio into @lineType1Sum,@lineType2Sum,@lineType3Sum while(@@FETCH_STATUS=0) begin set @lineTypeAllSum=@lineType1Sum+@lineType2Sum+@lineType3Sum --三者之和,这个值也是待填上的 /*下面获得一行的4个比例的值,4位数,3位小数的形式*/ declare @decml1 decimal(4,3),@decml2 decimal(4,3),@decml3 decimal(4,3),@decml4 decimal(4,3) --小数,共4位,小数点后有3位(就1.000 0.223 0.022 0.003这几种情况) if(@allSingleTotal=0) set @decml1=0 --每行的专场比例 else set @decml1=@lineType1Sum*1.0/@allSingleTotal --注意*1.0 if(@allMediumTotal=0) set @decml2=0 --每行的中型比例 else set @decml2=@lineType2Sum*1.0/@allMediumTotal --注意*1.0 if(@allBigTotal=0) set @decml3=0 --大型 else set @decml3=@lineType3Sum*1.0/@allBigTotal if(@allTypeTotal=0) set @decml4=0 --总计 else set @decml4=@lineTypeAllSum*1.0/@allTypeTotal /*下面对小数进行处理,得到百分比形式的除了百分号的值*/ declare @temp1 decimal(4,1),@temp2 decimal(4,1),@temp3 decimal(4,1),@temp4 decimal(4,1)-- --转化成共四位,一位小数的百分比前面的数值,即 100.0 40.3 5.4 0.4 set @temp1=CAST(100*@decml1 as decimal(4,1)) set @temp2=CAST(100*@decml2 as decimal(4,1)) set @temp3=CAST(100*@decml3 as decimal(4,1)) set @temp4=CAST(100*@decml4 as decimal(4,1)) /*好了,可以更新了*/ update #lastTable set type1Ratio=CAST(@temp1 as varchar(10))+'%', type2Ratio=CAST(@temp2 as varchar(10))+'%', type3Ratio=CAST(@temp3 as varchar(10))+'%', allTypeSum=@lineTypeAllSum, allTypeRatio=CAST(@temp4 as varchar(10))+'%' where current of curToFillRatio fetch next from curToFillRatio into @lineType1Sum,@lineType2Sum,@lineType3Sum end close curToFillRatio deallocate curToFillRatio /*插入总计的行*/ insert into #lastTable values(40, '总计',@allSingleTotal,'100.0%', @allMediumTotal,'100.0%', @allBigTotal,'100.0%', @allTypeTotal,'100.0%') /*最后只获取一个结果表*/ select * from ( select top 100 * from #lastTable where provinceId!=40 order by allTypeSum desc --注意这里必须要top这样的语句 )T union all select * from #lastTable where provinceId=40 END