如何将Totals添加到CTE生成的行组中

时间:2017-02-27 09:55:08

标签: sql sql-server sql-server-2008

我有这个CTE。我的目标是显示结果集中的所有行以及具有相同值的列的列的总数。

WITH CTEVal AS 
(SELECT RNum, Amount, Tag, TAmount, 
ROW_NUMBER() OVER(ORDER BY CONVERT(DATETIME, TDate, 101) DESC) AS RowNum 
from [dbo].[viewJD])

SELECT TDate, RNum, 
  CASE WHEN Tag = 'DR' THEN CONVERT(VARCHAR(50),Amount) ELSE '0.00' END AS Debit,
  CASE WHEN Tag = 'CR' THEN CONVERT(VARCHAR(50),Amount) ELSE '0.00' END AS Credit FROM CTEVal

返回结果集

TDate       Rnum    Debit    Credit
12-22-2015   8      100       0.00
12-22-2015   8      300       0.00
12-22-2015   8      0.00      400
12-22-2015   9      250       0.00    
12-22-2015   9      250       0.00    
12-22-2015   9      0.00      500   
12-23-2015   10     600       0.00    
12-23-2015   10     0.00      100     
12-23-2015   10     0.00      500

预期结果集

TDate       Rnum    Debit    Credit
12-22-2015   8      100       0.00
12-22-2015   8      300       0.00
12-22-2015   8      0.00      400
            TOTAL   400       400
12-22-2015   9      250       0.00    
12-22-2015   9      250       0.00    
12-22-2015   9      0.00      500   
            TOTAL   500       500
12-23-2015   10     600       0.00    
12-23-2015   10     0.00      100     
12-23-2015   10     0.00      500
            TOTAL   600       600

从viewJD中选择*将返回

TDate       Rnum    Amount    Tag   TAmount
12-22-2015   8      100       DR    400
12-22-2015   8      300       DR    400
12-22-2015   8      400       CR    400
12-22-2015   9      250       DR    500       
12-22-2015   9      250       DR    500       
12-22-2015   9      500       CR    500       
12-23-2015   10     600       DR    600       
12-23-2015   10     100       CR    600       
12-23-2015   10     500       CR    600       

DR的总和= CR的总和= TAmount

2 个答案:

答案 0 :(得分:0)

您在预期输出中提供的格式不可行或不可取。以下代码将它们存储为单独的列。

SELECT  TDate,
        RNum, 
        CASE WHEN Tag = 'DR' THEN Amount ELSE 0.00 END AS Debit,
        CASE WHEN Tag = 'CR' THEN Amount ELSE 0.00 END AS Credit,
        (select sum(Amount)
            from [dbo].[viewJD] td2
            where td2.RNum = td1.RNum
                and Tag = 'DR') as Debit_Total,
        (select sum(Amount)
            from [dbo].[viewJD] td2
            where td2.RNum = td1.RNum
                and Tag = 'CR') as Credit_Total
    FROM [dbo].[viewJD] td1

这将为您提供类似

的输出
TDate       Rnum    Debit    Credit  Debit_Total  Credit_Total
12-22-2015   8      100       0.00     400.00        400.00
12-22-2015   8      300       0.00     400.00        400.00
12-22-2015   8      0.00      400      400.00        400.00
12-22-2015   9      250       0.00     500.00        500.00    
12-22-2015   9      250       0.00     500.00        500.00    
12-22-2015   9      0.00      500      500.00        500.00   
12-23-2015   10     600       0.00     600.00        600.00    
12-23-2015   10     0.00      100      600.00        600.00     
12-23-2015   10     0.00      500      600.00        600.00

不是最好看,但最容易在其他查询中使用。

答案 1 :(得分:0)

我有一个解决方案。我知道这不是一个好的解决方案。我尝试过使用Rollup但无法获得确切的结果格式。所以我想出了这个。 这确实是一个很长的解决方案。 但我希望你能从中得到一些解决问题的想法。

这里我首先将Debit和Credit分隔值转换为表变量。 然后我将SUM应用于值并将完整的结果带到cte。 我申请了DENSE_RANK以获得正确的订购,以便“总共”#39;排在详细行之后。 最后从cte中选择了具有值' Total'对于显示' total'。

的行的列RNum
CREATE TABLE viewJD
( 
TDate Date,
Rnum INT,
Amount INT,
Tag VARCHAR(2),
TAmount INT
)

INSERT INTO viewJD 
VALUES
('12-22-2015',   8   ,   100 ,      'DR',    400),
('12-22-2015' ,  8  ,    300  ,     'DR' ,   400),
('12-22-2015',   8  ,    400  ,     'CR' ,   400),
('12-22-2015' ,  9  ,    250  ,     'DR' ,   500 ),      
('12-22-2015' ,  9  ,    250  ,     'DR' ,   500 ),      
('12-22-2015' ,  9  ,    500 ,      'CR' ,   500 ),      
('12-23-2015' ,  10  ,   600 ,      'DR'  ,  600 ),      
('12-23-2015' ,  10 ,    100  ,     'CR' ,   600 ),      
('12-23-2015' ,  10  ,   500  ,     'CR' ,   600  )

DECLARE @ValTable TABLE
(
TDate Date,
Rnum INT,
Debit INT,
Credit INT
)

INSERT INTO @ValTable 
SELECT TDate, RNum,
  CASE WHEN Tag = 'DR' THEN Amount ELSE 0.00 END AS Debit,
  CASE WHEN Tag = 'CR' THEN Amount ELSE 0.00 END AS Credit 
FROM viewJD

;WITH cte 
AS (
    SELECT *,RowOrder=DENSE_RANK() OVER (PARTITION BY NULL ORDER By RNUM)     from @ValTable
    UNION ALL
    SELECT  NULL,
        RNum ,
        SUM([Debit]) AS Debit,
        SUM([Credit]) AS Credit ,
        RowOrder  =DENSE_RANK() OVER (PARTITION BY NULL ORDER By RNUM)                  
    FROM @ValTable 
    GROUP BY TDate,RNum

)

SELECT TDate,
    Rnum = CASE WHEN TDate IS NULL THEN 'Total' ELSE     CONVERT(VARCHAR(20),Rnum ) END, 
    Debit,
    Credit 
FROM cte 
ORDER BY roworder,Rnum,TDate DESC

DROP TABLE viewJD