列和行的枢轴总数未显示正确值

时间:2017-02-13 05:18:28

标签: sql-server sql-server-2014

老实说,好几天,我正在努力了解数据透视表的行为。右边,我能够在数据透视表中显示行和列的总和。这是我试图设置的代码

DECLARE @cols            AS NVARCHAR(MAX)
DECLARE @colswithNoNulls AS NVARCHAR(MAX)
DECLARE @query           AS NVARCHAR(MAX)
DECLARE @tanggal_awal       DATE
DECLARE @tanggal_akhir      DATE
DECLARE @print              NVARCHAR(MAX)
DECLARE @querycount      AS NVARCHAR(MAX)

CREATE TABLE #datatable  
(
    product_id int,
    product_date date,
    product_ammount int
)


SET @tanggal_awal   = convert(DATE,'02-01-2017')
SET @tanggal_akhir  = convert(DATE,DATEADD(dd,-1,(DATEADD(mm,1,@tanggal_awal))))

--SELECT DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,GETDATE())+1,0))

INSERT INTO #datatable (product_id,product_date,product_ammount) VALUES 
            (1,GETDATE(),100),
            (1,GETDATE(),900),
            (2,DATEADD(DD,-1,GETDATE()),400),
            (3,DATEADD(DD,4,GETDATE()),300),
            (1,DATEADD(DD,4,GETDATE()),200),
            (2,DATEADD(DD,2,GETDATE()),700),
            (4,DATEADD(DD,-3,GETDATE()),1000),
            (4,DATEADD(MM,1,GETDATE()),200),
            (4,GETDATE(),750)

;WITH CTE (datelist,maxdate) AS 
(
    SELECT CONVERT(INT,(MIN(DATEPART(day,@tanggal_awal)))) datelist, CONVERT(INT,MAX(DATEPART(day,product_date))) maxdate
    FROM #datatable
    UNION ALL
    SELECT CONVERT(INT,(DATEPART(day,datelist))), CONVERT(INT,(DATEPART(day,@tanggal_akhir)))
    FROM cte
    WHERE datelist < maxdate
) SELECT c.datelist 
    INTO #temp
    FROM cte c
    ORDER BY c.datelist
    OPTION (maxrecursion 0)

SELECT @cols =  STUFF((SELECT ',' + QUOTENAME(CONVERT(int, datelist)) 
                FROM #temp
                GROUP BY datelist
                ORDER BY CONVERT(int, datelist)
                FOR XML PATH(''), TYPE
                ).value('.', 'NVARCHAR(MAX)') 
                ,1,1,''
                ) 


SELECT @colswithNoNulls =   STUFF((SELECT ',ISNULL(' + QUOTENAME(CONVERT(int, datelist))  +',''0'') '+ QUOTENAME(CONVERT(int, datelist)) 
                            FROM #temp
                            GROUP BY datelist
                            ORDER BY CONVERT(int, datelist)
                            FOR XML PATH(''), TYPE
                            ).value('.', 'NVARCHAR(MAX)') 
                            ,1,1,'')

SET @query = 
          'SELECT product_id, '+ @colswithNoNulls+', Total FROM 
             (
                select 
                ISNULL((CAST(b.product_id as nvarchar(30))), ''Total'') product_id, 
                coalesce(b.product_ammount,0) as product_ammount, 
                DATEPART(dd,(convert(CHAR(10), product_date, 120))) PivotDate, 
                SUM(product_ammount) over (partition by b.product_id) as Total
                FROM #datatable b
                WHERE product_date between @tanggal_awal and @tanggal_akhir
                GROUP BY product_ammount,product_date,product_id
                WITH ROllup
            ) x
            pivot 
            (
                sum(product_ammount)
                for PivotDate in (' +@cols+ ')
            ) p
            ORDER BY CASE when (product_id = ''Total'') then 1 else 0 end, product_id'          

EXECUTE sp_executesql @query ,N'@tanggal_awal DATE, @tanggal_akhir DATE', @tanggal_awal,@tanggal_akhir

IF(OBJECT_ID('tempdb.dbo.#temp','U') IS NOT NULL)
    BEGIN
        TRUNCATE TABLE #temp
        TRUNCATE TABLE #datatable
        DROP TABLE #temp
        DROP TABLE #datatable
    END
ELSE
    BEGIN
        SELECT '#temp is not created in this script' AS MESSAGE
    END

如您所见,结果显示在显示屏上。然而,最右下角的总价值很奇怪,因为它像是这个图片中的精确总值的两倍: enter image description here 如何解决这个问题btw?因为它对我来说有点混乱。谢谢你的帮助:))

1 个答案:

答案 0 :(得分:1)

通常,我不完全了解RollUp功能。从你的PIVOT查询。我发现一些空行正在出现(基本上来自“With Rollup”选项的小计行),所以我稍微修改了Group by语句以达到预期的结果。

                select 
            ISNULL((CAST(b.product_id as nvarchar(30))), 'Total') product_id, 
            coalesce(b.product_ammount,0) as product_ammount, 
            DATEPART(dd,(convert(CHAR(10), product_date, 120))) PivotDate, 
            SUM(product_ammount) over (partition by b.product_id) as Total
            FROM #datatable b
            WHERE product_date between @tanggal_awal and @tanggal_akhir
            GROUP BY product_ammount,product_date,ROllup(product_id)

请在PIVOT中替换此查询,然后您将获得所需的输出。

注意:抱歉,我不完全了解RollUp功能,所以我无法给出正确的解释。