2017-02-13 37 views
0

說實話,好幾天,我正在嘗試瞭解數據透視錶行爲。 rightnow,我能夠顯示數據透視表中的行和列的總和。這裏是我試圖設置的代碼針對列和行的樞軸總計未顯示正確的值

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 (' [email protected]+ ') 
      ) 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

通常,我不完全知道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功能,所以我無法給出正確的解釋。

+0

所以我不應該彙總每一列?順便說一句,你有關於彙總行爲的任何解釋嗎?我正在考慮使用立方體,但並不是那麼棒。 –

+0

抱歉,目前我沒有關於彙總行爲的任何解釋,我最終只從您的帖子中聽說過Rollup。我對PIVOT表有了解,這有助於我找到答案 –