使用SQL Server进行数据透视

时间:2016-03-24 07:56:13

标签: sql-server pivot

我上次使用mysql发布了类似的问题。但是这次我想使用SQL服务器获取总数量值。我也发布了我的代码。请检查

DB Schema ===

CREATE DATABASE test;

CREATE TABLE [dbo].[RAccounts_Receivable](
    [id] [int] NOT NULL,
    [trntypename] [nvarchar](max) NULL,
    [datecreated] [date] NULL,
    [AmountDue] [decimal](18, 0) NULL) ;

INSERT INTO [dbo].[RAccounts_Receivable] 
(id, trntypename,datecreated,AmountDue )
VALUES
(1, 'Pay Bills', '2016-01-02', 50),
(2, 'Pay Bills', '2016-01-10', 60),
(3, 'Sales Returns', '2016-01-20', 30),
(4, 'Sales Returns', '2016-01-15', 20),
(5, 'Pay Bills', '2016-02-15', 10),


(6, 'Sales Returns', '2016-02-20', 20),
(7, 'Sales Returns', '2016-02-15', 10)
到目前为止

代码

SELECT * FROM 
            (SELECT FORMAT(datecreated,'yyyyMM') AS date
            ,SUM(AmountDue) AS AmountDue
            ,trntypename
    FROM RAccounts_Receivable
    WHERE 
            (trntypename='Pay Bills' OR trntypename='Sales Return')
            AND datecreated >= DATEADD(month, DATEDIFF(month, 0, GETDATE())-7, 0) 
            GROUP By [trntypename],FORMAT(datecreated,'yyyyMM')) AS Basedata 

PIVOT
(
  SUM(AmountDue) FOR date IN ([201601],[201602])
) AS p 

迄今为止的结果

trntypename | 201601 | 201602

Pay Bills   | 110    | 10
Sales Return| 50     | 30  

预期结果

trntypename | 201601 | 201602 | total

Pay Bills   | 110    | 10     | 120 
Sales Return| 50     | 30     | 80
total       | 160    | 40     | 200 

我仍然无法获得总数。

3 个答案:

答案 0 :(得分:1)

下面的代码罚款。我创建了一个临时表,你可以用它替换它 你的桌名;

WITH CodeSoFar AS(
SELECT * FROM 
        (SELECT CONVERT(nvarchar(6), datecreated,112) AS date
         ,SUM(AmountDue) AS AmountDue
         ,trntypename
         FROM ##RAccounts_Receivable

WHERE   (trntypename='Pay Bills' OR trntypename='Sales Returns')
        AND datecreated >= DATEADD(month, DATEDIFF(month, 0, GETDATE())-7, 0) 
         GROUP By [trntypename],CONVERT(nvarchar(6), datecreated,112)
        ) AS ABC

 PIVOT
 (
   SUM(AmountDue) FOR date IN ([201601],[201602])
 ) AS p
 )
 SELECT *,[201601]+[201602] AS Total FROM  CodeSoFar
 UNION
 SELECT 'Total' AS Total,SUM([201601]) AS '201601',SUM([201602]) AS  '201602',Sum([201601]+[201602])
 FROM  CodeSoFar

答案 1 :(得分:0)

我会形成我的查询,看起来像这样。

SELECT  CASE WHEN GROUPING(trntypename) = 1 THEN 'Total' ELSE trntypename END AS trntypename,
        SUM(CASE WHEN FORMAT(datecreated,'yyyyMM') = '201601' THEN AmountDue END) AS [201601],
        SUM(CASE WHEN FORMAT(datecreated,'yyyyMM') = '201602' THEN AmountDue END) AS [201602],
        SUM(AmountDue) Total
FROM    RAccounts_Receivable
WHERE   (trntypename = 'Pay Bills'
         OR trntypename = 'Sales Returns')
        AND datecreated >= DATEADD(month,DATEDIFF(month,0,GETDATE()) - 7,0)
GROUP BY ROLLUP([trntypename])
ORDER BY CASE WHEN GROUPING(trntypename) = 1 THEN '1' ELSE 0 END

总行是使用ROLLUP()创建的,其他总计是使用SUM(CASE)

创建的

为了动态生成它。你可以使用这样的东西。

DECLARE @CaseQuery NVARCHAR(MAX) = 'SUM(CASE WHEN FORMAT(datecreated,''yyyyMM'') = ''<<dateval>>'' THEN AmountDue END) AS [<<dateval>>]',
        @SelectQuery NVARCHAR(MAX),
        @Sql NVARCHAR(MAX)

SELECT  @SelectQuery = COALESCE(@SelectQuery + ',', '') + REPLACE(@CaseQuery, '<<dateval>>', FORMAT(datecreated,'yyyyMM'))
FROM    [dbo].[RAccounts_Receivable]
WHERE   datecreated >= DATEADD(month,DATEDIFF(month,0,GETDATE()) - 7,0)
GROUP BY FORMAT(datecreated,'yyyyMM')
ORDER BY FORMAT(datecreated,'yyyyMM')

SET     @Sql = '
    SELECT  CASE WHEN GROUPING(trntypename) = 1 THEN ''Total'' ELSE trntypename END AS trntypename, ' + 
            @SelectQuery + ',
            SUM(AmountDue) Total
    FROM    RAccounts_Receivable
    WHERE   (trntypename = ''Pay Bills''
             OR trntypename = ''Sales Returns'')
            AND datecreated >= DATEADD(month,DATEDIFF(month,0,GETDATE()) - 7,0)
    GROUP BY ROLLUP([trntypename])
    ORDER BY CASE WHEN GROUPING(trntypename) = 1 THEN 1 ELSE 0 END
'
EXEC    (@Sql)

变量用于构建SUM(CASE)以及将通过调用EXEC(@SQL)执行的SQL

答案 2 :(得分:0)

SELECT * FROM 
            (SELECT FORMAT(datecreated,'yyyyMM') AS date
            ,SUM(AmountDue) AS AmountDue
            ,trntypename
    FROM RAccounts_Receivable
    WHERE 
            (trntypename='Pay Bills' OR trntypename='Sales Return')
            AND datecreated >= DATEADD(month, DATEDIFF(month, 0, GETDATE())-7, 0) 
            GROUP By [trntypename],FORMAT(datecreated,'yyyyMM')) AS Basedata 

PIVOT
(
  SUM(AmountDue) FOR date IN ([201601],[201602])
) AS p

union 

SELECT 'total',sum([201601]) as '201601',sum([201602]) as '201602' FROM 
            (SELECT FORMAT(datecreated,'yyyyMM') AS dt
            ,SUM(AmountDue) AS [AmountDue]
            ,trntypename
    FROM RAccounts_Receivable
    WHERE 
            (trntypename='Pay Bills' OR trntypename='Sales Return')
            AND datecreated >= DATEADD(month, DATEDIFF(month, 0, GETDATE())-7, 0) 
            GROUP By [trntypename],FORMAT(datecreated,'yyyyMM')) AS Basedata 

PIVOT
(
  SUM(AmountDue) FOR dt IN ([201601],[201602])
) AS p