Sql server PIVOT查询不返回数据

时间:2013-12-11 12:52:39

标签: sql sql-server pivot

我试图以下面的方式显示PIVOT格式的数据

Days       2009-APR    2010-APR      2009-DEC    2010-DEC
----------- ----------- -----------  ----------- -----------
1           0           0             0           0
2           0           0             0           0
3           0           0             0           0
4           0           0             0           0
5           0           0             0           0
6           0           0             0           0
7           0           0             0           0
8           0           0             0           0
9           0           0             0           0
30          0           0             0           0
31          0           0             0           0

这是我的数据透视查询返回结果,但所有值都为0.无法捕获问题。所以请指导我问题在哪里。

WITH months(MonthNumber) AS
(
    SELECT 1
    UNION ALL
    SELECT MonthNumber+1 
    FROM months
    WHERE MonthNumber < 31
)
    Select MonthNumber,isnull([2009-APR],0)     
as [2009-APR],isnull([2010-APR],0)     
as [2010-APR],isnull([2009-MAY],0)     
as [2009-MAY],isnull([2010-MAY],0)     
as [2010-MAY],isnull([2009-JUL],0)     
as [2009-JUL],isnull([2010-JUL],0)     
as [2010-JUL],isnull([2009-NOV],0)     
as [2009-NOV],isnull([2010-NOV],0)     
as [2010-NOV],isnull([2009-DEC],0)     
as [2009-DEC],isnull([2010-DEC],0)     
as [2010-DEC] from (    
    select MonthNumber,CAST(YEAR(CurDate) AS VARCHAR)+'-'+CAST(MONTH(CurDate) AS VARCHAR) AS  years,
    isnull(Warranty_Info,0) as Warranty_Info  from EOD_Main    
          right join months on DAY(CurDate ) = MonthNumber   
    ) as xx    
    PIVOT     
    (    
    SUM(Warranty_Info) FOR years IN ([2009-APR],[2010-APR],[2009-MAY],[2010-MAY],[2009-JUL],[2010-JUL],[2009-NOV],[2010-NOV],[2009-DEC],[2010-DEC])    
    )    
    as pvt ORDER BY MonthNumber

这样我就可以检查2010年的任何数据是否存在。 12月份,发现数据存在。

   select sum(Warranty_Info) from EOD_Main
    where year(CurDate)=2010 and month(CurDate)=12

所以请指导我如何构建将返回年度和数据的正确数据的数据透视查询。一个月明智。感谢

FULL SCRIPT

ALTER PROC WarrantyTrendDetails  
(  
 @StYear AS INT,  
 @EdYear  AS INT,  
 @SelectedMonths AS VARCHAR(MAX)  
)  
AS  

--DECLARE @SelectedMonths VARCHAR(MAX)  
DECLARE @TmpSelectedMonths VARCHAR(MAX)  
--SET @SelectedMonths='JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC'  
--SET @SelectedMonths='APR,MAY,JUL,NOV,DEC'  
SET @TmpSelectedMonths=@SelectedMonths  
--SELECT * FROM StringToTable(@SelectedMonths,',')  

DECLARE @StartYear AS INT,  
        @EndYear  AS INT  

DECLARE @ConCatData VARCHAR(MAX)  
DECLARE @TmpData VARCHAR(MAX)  
DECLARE @years varchar(max), @yearsColumns varchar(max)     
DECLARE @query varchar(max)      



SET @ConCatData=''  

SET @TmpData = ''  
SET @StartYear=@StYear  
SET @EndYear=@EdYear  



WHILE LEN(@TmpSelectedMonths) > 0  
BEGIN  
SET @StartYear=@StYear  
SET @EndYear=@EdYear  

 WHILE( @StartYear <= @EndYear )  
 BEGIN  
  SET @TmpData= LEFT(@TmpSelectedMonths, CHARINDEX(',', @TmpSelectedMonths+',')-1)  
  SET @ConCatData = @ConCatData + (CAST(@StartYear AS VARCHAR)+'-'+@TmpData)+','  
  SET @StartYear=@StartYear+1  
 END  
 SET @TmpSelectedMonths = STUFF(@TmpSelectedMonths, 1, CHARINDEX(',', @TmpSelectedMonths+','), '')  
END  

SET @TmpSelectedMonths=@SelectedMonths  
SET @ConCatData=SUBSTRING (@ConCatData,1,LEN(@ConCatData)-1)  


SELECT @years=COALESCE(@years+',','')   +'['+ cast(data as varchar(8))+']',      
@yearsColumns=COALESCE(@yearsColumns+',','')   +'isnull(['+ cast(data as varchar(8))+'],0)       
as ['+cast(data as varchar(8))+']'      
FROM StringToTable(@ConCatData,',')     

SET @query = 'WITH months(MonthNumber) AS  
(  
    SELECT 1  
    UNION ALL  
    SELECT MonthNumber+1   
    FROM months  
    WHERE MonthNumber < 31  
)  
 Select MonthNumber Days,'+@yearsColumns+' from (      
    select MonthNumber,CAST(YEAR(CurDate) AS VARCHAR)+''-''  
 +CAST(datename(month, CurDate) AS VARCHAR(3)) AS  years,  
 isnull(Warranty_Info,0) as Warranty_Info  from EOD_Main      
          right join months on DAY(CurDate ) = MonthNumber     
    ) as xx      
    PIVOT       
    (      
  SUM(xx.Warranty_Info) FOR years IN ('+@years+')      
    )      
    as pvt ORDER BY Days'      
    --PRINT @query      
    EXEC(@query)      

GO



ALTER PROC [dbo].[WarrantyTrends]    
(    
 @StartYr AS INT,    
 @EndYr  AS INT     
)    
AS    
 DECLARE @query varchar(max)    
 DECLARE @years varchar(max), @yearsColumns varchar(max)    

 SELECT 1 mID, 'January' as month  into #tempMonths   UNION ALL     
    SELECT 2,'February' as month     UNION ALL     
    SELECT 3,'March' as month     UNION ALL     
    SELECT 4,'April' as month     UNION ALL     
    SELECT 5,'May' as month     UNION ALL     
    SELECT 6,'June' as month     UNION ALL     
    SELECT 7,'July' as month     UNION ALL     
    SELECT 8,'August' as month     UNION ALL     
    SELECT 9,'September' as month     UNION ALL     
    SELECT 10,'October' as month    UNION ALL     
    SELECT 11,'November' as month    UNION ALL     
    SELECT 12,'December' as month      


    SELECT @years=COALESCE(@years+',','')   +'['+ cast(years as varchar(4))+']',    
    @yearsColumns=COALESCE(@yearsColumns+',','')   +'isnull(['+ cast(years as varchar(4))+'],0)     
    as ['+cast(years as varchar(4))+']'    
    from  (select distinct YEAR(CurDate) years from EOD_Main    
 WHERE YEAR(CurDate)>=@StartYr AND YEAR(CurDate)<=@EndYr     
 ) as x ORDER BY years  

 SET @query = 'Select months,'+@yearsColumns+' from (    
    select mID, YEAR(CurDate)  years,[MONTH] months,      
    isnull(Warranty_Info,0) as Warranty_Info  from EOD_Main    
          right join #tempMonths on datename(month,CurDate ) =[month]     
    ) as xx    
    PIVOT     
    (    
    SUM(xx.Warranty_Info) FOR years IN ('+@years+')    
    )    
    as pvt ORDER BY mID'    
    PRINT @query    
    EXEC(@query)    

   drop table #tempMonths       

GO  

1 个答案:

答案 0 :(得分:4)

现有查询存在一些问题导致结果出错。

首先,您在子查询中创建一个字符串并将列转换为varchar - 您需要确保指定字符串的长度。

其次,在子查询中,您使用CurDate列上的MONTH()函数。 month()函数返回一个整数而不是字符串 - 因此您要创建一个年 - 月组合,如下所示:

years
2009-8
2009-9

这通常不是问题,但您的PIVOT正在创建名称为2009-AUG等的新列。您的PIVOT正在引用不存在的值。

为了解决这个问题,您需要在子查询中使用DATENAME()函数,使用:

CAST(datename(month, CurDate) AS VARCHAR(3)) 

这将使用AUGAPR等名称创建您的月份,使您的完整查询类似于:

;WITH months(MonthNumber) AS
(
    SELECT 1
    UNION ALL
    SELECT MonthNumber+1 
    FROM months
    WHERE MonthNumber < 31
)
select *
from
(
  select MonthNumber,
    CAST(YEAR(CurDate) AS VARCHAR(4))
    +'-'+UPPER(CAST(datename(month, CurDate) AS VARCHAR(3))) AS  years,
    isnull(Warranty_Info,0) as Warranty_Info 
  from EOD_Main     
  right join months 
    on DAY(CurDate ) = MonthNumber  
) d
PIVOT     
(    
  SUM(Warranty_Info) 
  FOR years IN ([2009-AUG],[2009-SEP])    
) as pvt 
ORDER BY MonthNumber;

请参阅SQL Fiddle with Demo