SQL 服务器的数据透视总数
Pivot total with SQL Server
我上次使用 mysql 发布了类似的问题。但是这次我想使用 SQL 服务器获得总的枢轴值。我也在发布我的代码。请检查
数据库模式===
创建数据库测试;
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
我还是无法得到总数。
下面的代码可以正常工作。我创建了一个临时 table 你可以用
你的 table 名字;
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
我会形成我的查询看起来像这样。
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)
变量用于构建将通过调用EXEC(@SQL)
执行的SUM(CASE)
和SQL
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
我上次使用 mysql 发布了类似的问题。但是这次我想使用 SQL 服务器获得总的枢轴值。我也在发布我的代码。请检查
数据库模式===
创建数据库测试;
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
我还是无法得到总数。
下面的代码可以正常工作。我创建了一个临时 table 你可以用 你的 table 名字;
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
我会形成我的查询看起来像这样。
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)
变量用于构建将通过调用EXEC(@SQL)
SUM(CASE)
和SQL
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