如何减去连续行中的值?

时间:2017-07-11 07:21:06

标签: sql-server

我在下面的表格中有一些数据。

CREATE TABLE #NetProfit (ID int, [Name] varchar(50),[Class] varchar(50), Balance money)
 go
 --Populate Sample records
 INSERT INTO #NetProfit VALUES(4,'Income','No Class',303386.8462)
 INSERT INTO #NetProfit VALUES(6,'Expenses','No Class',22443.5317)
 INSERT INTO #NetProfit VALUES(4,'Income','2 TestUser3',0.00)
 INSERT INTO #NetProfit VALUES(5,'Cost','2 TestUser3',0.3875)
 INSERT INTO #NetProfit VALUES(6,'Expenses','2 TestUser3',6439.2129)
 INSERT INTO #NetProfit VALUES(5,'Cost','3 TestUser3',0.1395)
 INSERT INTO #NetProfit VALUES(6,'Expenses','3 TestUser3',6451.6129)
 INSERT INTO #NetProfit VALUES(5,'Cost','38 Code#1012',3.0225)
 INSERT INTO #NetProfit VALUES(6,'Expenses','38 Code#1012',30.225) 
 go
 select * from #NetProfit
 drop table #NetProfit

+----+----------+--------------+-------------+
| ID |   Name   |    Class     |   Balance   |
+----+----------+--------------+-------------+
|  4 | Income   | No Class     | 303386.8462 |
|  6 | Expenses | No Class     | 22443.5317  |
|  4 | Income   | 2 TestUser3  | 0           |
|  5 | Cost     | 2 TestUser3  | 0.3875      |
|  6 | Expenses | 2 TestUser3  | 6439.2129   |
|  5 | Cost     | 3 TestUser3  | 0.1395      |
|  6 | Expenses | 3 TestUser3  | 6451.6129   |
|  5 | Cost     | 38 Code#1012 | 3.0225      |
|  6 | Expenses | 38 Code#1012 | 30.225      |
+----+----------+--------------+-------------+

我想通过[Class]列减去[Balance]列行方式组。 对于前者每个[类]列的NetProfit =(收入 - 成本 - 费用),按[类别]分组。

这是我期待的输出。

+-------------+-------------+-------------+--------------+
|  No Class   | 2 TestUser3 | 3 TestUser3 | 38 Code#1012 |
+-------------+-------------+-------------+--------------+
| 280943.3145 | 6439.6004   | 6451.7524   | 33.2475      |
+-------------+-------------+-------------+--------------+

任何帮助将不胜感激。谢谢!

3 个答案:

答案 0 :(得分:0)

这可能是实现预期结果的第一步:

SELECT NP.Class, ABS(ISNULL(SUM(CASE NP.Name WHEN 'Income' THEN NP.Balance END), 0) - SUM(CASE NP.Name WHEN 'Income' THEN NULL ELSE NP.Balance END)) AS Balance
FROM #NetProfit AS NP
GROUP BY NP.Class;

然后你必须动态调整这些结果。静态地,您的查询应该如下所示:

SELECT *
FROM (
    SELECT NP.Class, ABS(ISNULL(SUM(CASE NP.Name WHEN 'Income' THEN NP.Balance END), 0) - SUM(CASE NP.Name WHEN 'Income' THEN NULL ELSE NP.Balance END)) AS Balance
    FROM #NetProfit AS NP
    GROUP BY NP.Class) AS SourceTable
    PIVOT (MAX(Balance) FOR Class IN ([2 TestUser3], [3 TestUser3], [38 Code#1012], [No Class])) AS PivotTable;

因此,通过插入动态SQL,结果如下:

DECLARE @SQL NVARCHAR(MAX);
DECLARE @Col NVARCHAR(MAX);

SET @Col = STUFF((   SELECT DISTINCT ',' + QUOTENAME(NP.Class)
                     FROM #NetProfit AS NP
                     FOR XML PATH('')), 1, 1, '');

SET @SQL = N'
SELECT *
FROM (
    SELECT NP.Class, ABS(ISNULL(SUM(CASE NP.Name WHEN ''Income'' THEN NP.Balance END), 0) - SUM(CASE NP.Name WHEN ''Income'' THEN NULL ELSE NP.Balance END)) AS Balance
    FROM #NetProfit AS NP
    GROUP BY NP.Class) AS SourceTable
    PIVOT (MAX(Balance) FOR Class IN (' + @Col + N')) AS PivotTable';

EXECUTE sys.sp_executesql @SQL;

输出结果:

+-------------+-------------+--------------+-------------+
| 2 TestUser3 | 3 TestUser3 | 38 Code#1012 |  No Class   |
+-------------+-------------+--------------+-------------+
| 6439,6004   | 6451,7524   | 33,2475      | 280943,3145 |
+-------------+-------------+--------------+-------------+

答案 1 :(得分:0)

此查询以行的形式返回计算。 使用数据透视表,您可以将行转换为列

select isnull(c1, c2), isnull(i, 0)-isnull(e,0) from (
 select * from 
 (select class c1, sum(balance) i
 from #NetProfit
 where Name = 'income'
 group by class) i
 full join
 (
 select class c2, sum(balance) e
 from #NetProfit
 where Name != 'income'
 group by class) e  on i.c1 = e.c2) t

答案 2 :(得分:-1)

试试这个(假设ID为4,收入为正,而其余则应视为否定;

 select 
    [Class No]=SUM(case when [Class]='No Class' then (case when ID=4 then Balance else Balance*-1 end) else 0 end),
    [TestUser2]=SUM(case when [Class]='2 TestUser3' then (case when ID=4 then Balance else Balance*-1 end) else 0 end),
    [TestUser3]=SUM(case when [Class]='3 TestUser3' then (case when ID=4 then Balance else Balance*-1 end) else 0 end),
    [Code#1012]=SUM(case when [Class]='Code#1012' then (case when ID=4 then Balance else Balance*-1 end) else 0 end)
 from 
    #NetProfit