如何构建前滚式 SSRS 报告

How to build a rolling forward SSRS report

我一直在编写一份报告,允许用户查看向前滚动的总数。

这个a是矩阵。我已经包含了一个关于数据是什么样子的示例。

报告应从 10 月开始计算 运行 总额,金额为 42 美元。然后报告将对账目进行总结。然后取 42 美元 + 64 美元 = 106 美元。 106 美元将结转至 12 月份,期初余额为 106 美元。

我正在处理的报告

报告示例

                     2016-011            2016-012

Beginning Balance       42                   106

AP                      31                    41
APAJ                    32                    42
CJ                      33                    43
GEN                    -32                   -42

Total Account           64                    84

Begin Bal + Total Acc  106                   190

数据示例

DECLARE @ClosingBalTemp TABLE
(
  Account_ID varchar(30),
  Period_Nbr varchar(10),
  Source_Code varchar(10),
  Closing_Balance_Amt numeric(16,2)
)

INSERT INTO @ClosingBalTemp (Account_ID, Period_Nbr, Source_Code, Closing_Balance_Amt)

    VALUES ('01-002-333', '2016-008', 'AP', 1),
           ('01-002-333', '2016-008', 'APAJ', 2),
           ('01-002-333', '2016-008', 'CJ', 3),
           ('01-002-333', '2016-008', 'GEN', -2),
           ('01-002-333', '2016-009', 'AP', 11),
           ('01-002-333', '2016-009', 'APAJ', 12),
           ('01-002-333', '2016-009', 'CJ', 13),
           ('01-002-333', '2016-009', 'GEN', -12),
           ('01-002-333', '2016-010', 'AP', 20),
           ('01-002-333', '2016-010', 'APAJ', 21),
           ('01-002-333', '2016-010', 'CJ', 23),
           ('01-002-333', '2016-010', 'GEN', -22),
           ('01-002-333', '2016-011', 'AP', 31),
           ('01-002-333', '2016-011', 'APAJ', 32),
           ('01-002-333', '2016-011', 'CJ', 33),
           ('01-002-333', '2016-011', 'GEN', -32),
           ('01-002-333', '2016-012', 'AP', 41),
           ('01-002-333', '2016-012', 'APAJ', 42),
           ('01-002-333', '2016-012', 'CJ', 43),
           ('01-002-333', '2016-012', 'GEN', -42)

SELECT * FROM @ClosingBalTemp


The data should look like this

The logic is almost working. The Bal type is not calculating the running balance correctly after Period 9. The 4.00 is coming from Oct that does not display.

B   BAL    2016 9   4.00
T   AP     2016 9   11.00
T   APAJ   2016 9   12.00
T   CJ     2016 9   13.00
T   GEN    2016 9   -12.00
B   BAL    2016 10  24.00     **Should be 33**
T   AP     2016 10  20.00
T   APAJ   2016 10  21.00
T   CJ     2016 10  23.00
T   GEN    2016 10  -22.00
B   BAL    2016 11  42.00     **Should be 75**
T   AP     2016 11  31.00
T   APAJ   2016 11  32.00
T   CJ     2016 11  33.00
T   GEN    2016 11  -32.00
B   BAL    2016 12  64.00     **Should be 139**
T   AP     2016 12  41.00
T   APAJ   2016 12  42.00
T   CJ     2016 12  43.00
T   GEN    2016 12  -42.00

在这里查看 runningvalue():https://msdn.microsoft.com/en-us/library/dd255229.aspx 这可以与组一起使用作为范围,因此可以在您的列组上使用。

我不认为 运行 总计会因为列布局而起作用。我们希望 2016-012 的顶部来自 2016-011 的底部。我会说我不太了解你的数据集,我做了很多 roll forwards/trial balancesHers's s post on Trial blances。但我确实相信我已经使用建议的存储过程使用 2008 年的东西解决了你的问题。理想情况下,year 和 period 将是单独的字段,以便更容易地计算周期。我现在只是硬编码它们。 使用输出,您可以在 SSRS 报告中为每个月创建一个列。您可以在 SSRS 中自行计算月末总计。 在 2008 年可能有更好的方法来执行此操作,但我的服务器上没有 2008,所以我无法测试。 (我会以不同方式处理期初余额摘要)

DECLARE @CurrentPeriod CHAR(10);
DECLARE @PriorPeriod CHAR(10);
DECLARE @PPPeriod CHAR(10)

SET @CurrentPeriod = '2016-012';
SET @PriorPeriod = '2016-011';
SET @PPPeriod = '2016-010';
-- First Step - Summarize the balances
WITH Balances (CurrentPeriodOpenBal, PriorPeriodOpenBal)
  AS (
     SELECT SUM(CASE WHEN cbt.Period_Nbr IN (@PPPeriod, @PriorPeriod)
            THEN cbt.Closing_Balance_Amt ELSE 0 END)
            AS CurrentPeriodOpenBal,
        SUM(CASE WHEN cbt.Period_Nbr IN (@PPPeriod) 
            THEN cbt.Closing_Balance_Amt ELSE 0 END) 
            AS PriorPeriodOpenBal
        FROM dbo.ClosingBalTemp cbt
        WHERE cbt.Period_Nbr < @CurrentPeriod
  )
-- Now we are going to combine our balances and our transaction
,
BalTrans (TransType, SourceCode, PeriodNbr, Amount) AS
(
SELECT 'B', 'BAL', @PriorPeriod, bal.PriorPeriodOpenBal 
FROM Balances bal   
UNION ALL 
SELECT 'B', 'BAL', @CurrentPeriod, bal.CurrentPeriodOpenBal 
FROM Balances  bal
UNION ALL  
SELECT 'T', trans.Source_Code, trans.Period_Nbr,  trans.Closing_Balance_Amt
   FROM dbo.ClosingBalTemp trans
  WHERE trans.Period_Nbr BETWEEN @PriorPeriod AND @CurrentPeriod
)
-- Now we simply order our transactions   
SELECT bt.TransType, bt.SourceCode, bt.PeriodNbr, bt.Amount FROM BalTrans bt
 ORDER BY bt.PeriodNbr, bt.TransType, bt.SourceCode

--- 修订版

-- First Step - convert period to fiscla year and period
WITH Trans AS
  (SELECT cbt.Account_ID, 
    cbt.Period_Nbr,
    CAST(SUBSTRING(cbt.Period_Nbr,1,4) AS INT) AS FiscalYear,
    CAST(SUBSTRING(cbt.Period_Nbr,6,3) AS INT) AS FiscalPeriod,
    cbt.Source_Code,
    cbt.Closing_Balance_Amt
    FROM dbo.ClosingBalTemp cbt) 


-- This gets the total balance for each period - we add one to the period
-- to figure out the opening info
, Balances ( FiscalYear, FiscalPeriod, OpenPeriod, Amount)
 AS (
  SELECT DISTINCT
       bal.FiscalYear,
       bal.FiscalPeriod,
       bal.FiscalPeriod + 1 AS OpenPeriod,
       SUM(bal.Closing_Balance_Amt) OVER(ORDER BY bal.Period_Nbr) AS Amount  
        FROM Trans bal
        WHERE bal.Period_Nbr >= @PPPeriod 
          AND bal.Period_Nbr  < @StartingPeriod
  )
-- Now we are going to combine our balances and our transaction
,

BalTrans (TransType, SourceCode, FiscalYear, FiscalPeriod, Amount) AS
(
 SELECT 'B', 'BAL', bl.FiscalYear, bl.OpenPeriod, bl.Amount FROM Balances bl    
UNION ALL 
SELECT 'T', trans.Source_Code, trans.FiscalYear, trans.FiscalPeriod, 
        trans.Closing_Balance_Amt
FROM Trans trans
WHERE trans.Period_Nbr BETWEEN @EndingPeriod AND @StartingPeriod
)   
SELECT bt.TransType, bt.SourceCode, bt.FiscalYear, Bt.FiscalPeriod,
 bt.Amount FROM BalTrans bt
ORDER BY bt.FiscalYear, bt.FiscalPeriod, bt.TransType, bt.SourceCode

-- 光标示例

DECLARE @EndPeriod CHAR(10);
DECLARE @StartPeriod CHAR(10);
DECLARE @PPPeriod CHAR(10)
-- Ideally, year and period would be separate integer fields
-- so one could calculate prior period from current Period.
-- But that's not the key part of the question 
SET @EndPeriod = '2016-012';
SET @StartPeriod = '2016-009';
SET @PPPeriod = '2016-008';

DECLARE @Period_Nbr CHAR(10);
DECLARE @Source_Code CHAR(10);
DECLARE @Closing_Balance_Amt NUMERIC(16,2);

DECLARE @ReportPeriod CHAR(10);
DECLARE @ReportBalance NUMERIC(16,2);

CREATE TABLE #Output 
( ID INTEGER IDENTITY (1,1) PRIMARY KEY,   
  Period_Nbr CHAR(10), 
  Source_Code CHAR(10),
  Closing_Balance_Amt numeric(10,2)
  )
  -- the following insures that SSRS sees the output correctly
IF 1=2
  BEGIN
     SELECT ID,
        Period_Nbr,
        Source_Code,
        Closing_Balance_Amt
        FROM #Output;
  END;

DECLARE OMGUAC CURSOR FAST_FORWARD FOR
  SELECT Period_Nbr, Source_Code, Closing_Balance_Amt
  FROM dbo.ClosingBalTemp
  WHERE Period_Nbr BETWEEN @PPPeriod AND @EndPeriod
  ORDER BY Period_Nbr, Source_Code;

OPEN OMGUAC;

FETCH NEXT FROM OMGUAC INTO @Period_Nbr,@Source_Code,@Closing_Balance_Amt;

SET @ReportPeriod = @Period_Nbr;
SET @ReportBalance = 0;

WHILE @@FETCH_STATUS = 0
  BEGIN 
    -- When the period Changes, print the opening balance
     IF @Period_Nbr <> @ReportPeriod    
        BEGIN 
            INSERT INTO #Output
                ( Period_Nbr ,
                  Source_Code ,
                  Closing_Balance_Amt
                )
            VALUES  (@Period_Nbr, 'Open Bal',@ReportBalance);
        END
 IF @Period_Nbr > @PPPeriod
    BEGIN 
        INSERT INTO #Output
                ( Period_Nbr ,
                  Source_Code ,
                  Closing_Balance_Amt
                )
        VALUES  (@Period_Nbr, @Source_Code,@Closing_Balance_Amt);
    END
  SET @ReportBalance = @ReportBalance + @Closing_Balance_Amt;
  SET @ReportPeriod = @Period_Nbr
  FETCH NEXT FROM OMGUAC INTO @Period_Nbr, @Source_Code,
 @Closing_Balance_Amt;
   END;
SELECT * FROM #Output 
ORDER BY ID;
DROP TABLE #Output;
CLOSE OMGUAC;
DEALLOCATE OMGUAC;