我试图以下面的方式显示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
所以请指导我如何构建将返回年度和数据的正确数据的数据透视查询。一个月明智。感谢
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
答案 0 :(得分:4)
现有查询存在一些问题导致结果出错。
首先,您在子查询中创建一个字符串并将列转换为varchar
- 您需要确保指定字符串的长度。
其次,在子查询中,您使用CurDate
列上的MONTH()
函数。 month()
函数返回一个整数而不是字符串 - 因此您要创建一个年 - 月组合,如下所示:
years
2009-8
2009-9
这通常不是问题,但您的PIVOT正在创建名称为2009-AUG
等的新列。您的PIVOT正在引用不存在的值。
为了解决这个问题,您需要在子查询中使用DATENAME()
函数,使用:
CAST(datename(month, CurDate) AS VARCHAR(3))
这将使用AUG
,APR
等名称创建您的月份,使您的完整查询类似于:
;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;