相信大家在处理数据库编程时,也许会常用到pivot运算符。今天把我近段时间处理的一个简单报表用到pivot运算符与大家分享一下。
比如,针对一个职员基础表tb_Employee(ID,EmpID,EmpName,DptNo,DptDesc,InDate,...),利用pivot分析职工流动率情况。在入职日期不确定的情况下,如何动态处理所要的结果为题。
即,如何实现:
SELECT DptNo,Dpt,[2000] AS Y2000,[2001] AS Y2001,[2002] AS Y2002,...,[2017] AS Y2017
FROM (
SELECT DptNo,DptDesc,YEAR(InDate) AS ExpYear
FROM tb_Employee WITH (NOLOCK)
) t PIVOT ( COUNT(ExpYear) FOR ExpYear IN([2000],[2001],[2002],...,[2017]) ) AS dptDetail
ORDER BY dptDetail
考虑到不同的部门入职(或离职)的年份不尽相同,要实现根据部门编号灵活呈现流动人员情况,比如编号“A01”的部门或许是2005年和2008年有入职(或离职)职员,而编号是“A02”的部门则是2002年、2005年、2010年及2012年有流动人员信息,等等。为灵活处理此类信息,我个人编写存储过程以动态实现需求,部分编码分享如下,请各位加以指点:
(一、)定义存储过程及需传入的参数
--
-- @ dptno varchar(20)
--1.声明变量
DECLARE @sql VARCHAR(2000),@sql2 VARCHAR(2000),@dptno VARCHAR(20)
SET @sql=‘SELECT DptNo‘
SET @sql2=‘COUNT(ExpYear) FOR ExpYear IN([1900]‘ --[1900]为虚设
SET @dptno=‘A01‘
--2. 利用游标确定该职工表的所有年份
--2.1. 定义游标
DECLARE cur_ExpYear CURSOR
FOR
SELECT ROW_NUMBER()OVER(ORDER BY t1.ExpYear) AS sn,t1.ExpYear
FROM (SELECT DISTINCT YEAR(InDate) AS ExpYear FROM tb_Employee) t1
--2.2. 打开游标
OPEN cur_ExpYear
--2.3. 使用游标
DECLARE @sn TINYINT,@expyear VARCHAR(10) FETCH NEXT FROM cur_ExpYear INTO @sn,@expyear
WHILE @@FETCH_STATUS=0
BEGIN
SET @sql=RTRIM(@sql)+‘,[‘[email protected]+‘]‘+‘ AS Y‘[email protected]
SET @sql2=RTRIM(@sql2)+‘,[‘[email protected]+‘]‘
NEXT FROM cur_ExpYear INTO @sn,@expyear
END
--2.4. 关闭游标并释放游标
CLOSE cur_ExpYear
DEALLOCATE cur_ExpYear
--3.实现目标
SET @sql=RTRIM(@sql) +‘ FROM (SELECT DptNo,YEAR(InDate) AS ExpYear FROM tb_Employee WITH (NOLOCK) ) t PIVOT
(‘ [email protected]+‘)‘ +‘) AS dptDetail ORDER BY DptNo ‘
PRINT (@sql)
EXEC (@sql)
至此,不管职工表如何变化都能实现需求。