相信大家在處理數據庫編程時,也許會常用到pivot運算符。今天把我近段時間處理的一個簡單報表用到pivot運算符與大家分享一下。
比如,針對一個職員基礎表tb_Employee(ID,EmpID,EmpName,DptNo,DptDesc,InDate,...),利用pivot分析職工流動率情況。在入職日期不確定的情況下,如何動態處理所要的結果為題。
即,如何實現:
SELECT DptNo,DptDesc,[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
執行結果顯示如圖1所示:
圖 1
考慮到不同的部門入職(或離職)的年份不盡相同,要實現根據部門編號靈活呈現流動人員情況,比如編號“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)+',['+@expyear+']'+' AS Y'+@expyear SET @sql2=RTRIM(@sql2)+',['+@expyear+']' 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 (' +@sql2+')' +') AS dptDetail ORDER BY DptNo ' PRINT (@sql) EXEC (@sql)
在輸入部門編號為"A01"時,執行則顯示如圖2所示:
圖 2
當輸入部門編號為"B02"時,執行顯示結果如圖3所示:
圖 3
至此,不管職工表如何變化都能實現需求。