【问题标题】:Running totals in a SQL view在 SQL 视图中运行总计
【发布时间】:2011-12-03 16:55:48
【问题描述】:

我正在尝试在 SQL Server 2008 的视图中获取运行总计

这是我的桌子

银行账户
------------
帐户 ID(密钥)
姓名
已创建

交易
------------
交易 ID (KEY)
描述
信用
借方
跨日期
已创建
帐户ID

到目前为止,这是我的查询..

选择 t.Created, t.Description, t.Credit, t.Debit, t.TransDate, t.TransactionID, ba.AccountID, (isnull(t.Credit,0)-isnull(t.Debit,0))+COALESCE((SELECT SUM(isnull(Credit,0)) - SUM(isnull(Debit,0)) FROM 交易 b 其中 b.TransDate

我得到的是..

TransDate 贷记借记 RunningTotal ------------------------------------ ---------- ----- ----------------- --------- 2011-10-08 20:14:00 NULL 12 49.25 2011-10-08 20:14:00 2.11 NULL 63.36 2011-10-07 20:14:00 42.25 NULL 61.25 2011-10-06 20:14:00 NULL 12.25 19 2011-10-05 20:14:00 31.25 空 31.25

它应该是什么样子...

TransDate 贷记借记运行总计 ------------------------------------ ---------- ----- ----------------- --------- 2011-10-08 00:31:32.957 NULL 12 51.36 2011-10-08 00:31:32.957 2.11 NULL 63.36 2011-10-07 00:31:32.957 42.25 NULL 61.25 2011-10-06 00:31:32.957 NULL 12.25 19 2011-10-05 00:31:32.960 31.25 空 31.25

我真的很接近.. 似乎同一天有 2 笔交易,计算不正确.. 有什么想法吗?

【问题讨论】:

    标签: sql sql-server sql-server-2008 aggregate-functions


    【解决方案1】:
    SELECT t.Created, t.Description, t.Credit, t.Debit, t.TransDate, t.TransactionID, ba.AccountID,
           coalesce((select sum(ISNULL(Credit,0) - ISNULL(Debit, 0)) 
                     from Transactions
                     where TransactionID <= t.TransactionID and 
                           AccountID = ba.AccountID and
                          convert(date, TransDate) = convert(date, t.TransDate)),0)
            AS [Running Total]
    
    FROM  Transactions t INNER JOIN
             dbo.BankAccounts ba ON t.AccountID = ba.AccountID
    

    【讨论】:

    • 似乎不起作用,并且缺少一个(合并后...我将编辑帖子以显示我得到的内容
    • 我相信问题可能出在您如何从日期获取 smalldate 的方式上,我会更新我的答案
    • 好的,我更新了,看到另一个变化是我将“Running Total”替换为 [Running Total],在我的测试中“Running Total”命名它不起作用
    • 接近了..现在加起来了,只是计算不正确,如果你看看我更新的结果,你会看到它应该是什么样子
    • 我查过了,但我看不出你是如何在“好”示例中计算运行总计的:我的意思是有 5、6、7 和 8 天的总数,所以为什么在第 6 天是你从前一天减去总数?
    【解决方案2】:

    如果这是 Oracle,那么就有 Window 函数。您可以使用 LEAD 和/或 LAG 对当前行执行相对于先前或即将到来的行的计算(基于排序顺序)

    【讨论】:

      【解决方案3】:

      我使用 ROW_NUMBERCTE,因为你在 2008 年

      WITH transactionTotal AS
      (
         SELECT t.Created, t.Description, t.Credit, t.Debit, t.TransDate, t.TransactionID, a.AccountID
            , ROW_NUMBER() OVER (ORDER BY TransDate ASC) AS RowNumber
            , ( ISNULL(t.Credit, 0) - ISNULL(t.Debit, 0) ) AS TransactionTotal
         FROM dbo.Transactions AS t 
         INNER JOIN dbo.BankAccounts AS a ON t.AccountID = a.AccountID
      )
      SELECT t.Created, t.Description, t.Credit, t.Debit, t.TransDate, t.TransactionID, t.AccountID
         , ( SELECT SUM(tt.TransactionTotal)
             FROM transactionTotal AS tt
             WHERE tt.RowNumber <= t.RowNumber) AS RunningTotal
      FROM transactionTotal AS t
      LEFT JOIN transactionTotal AS tt ON t.RowNumber = tt.RowNumber + 1
      ORDER BY t.TransDate DESC
      

      【讨论】:

      • 非常好!!几天来一直试图得到这个,只是不得不处理错误的总数,直到现在......把它放到一个视图中,它工作得很好
      【解决方案4】:

      --我会使用现有的身份列来 100% 确定我正在处理正确的交易。

      SELECT t.Created, t.Description, t.Credit, t.Debit, t.TransDate, t.TransactionID, ba.AccountID,
              (isnull(t.Credit,0)-isnull(t.Debit,0))+COALESCE((SELECT SUM(isnull(Credit,0)) - SUM(isnull(Debit,0))
                                    FROM Transactions b 
                                    WHERE b.TransactionID < t.TransactionID 
                                     and b.AccountID = t.AccountID),0)
                                       AS RunningTotal
      FROM  Transactions t 
      INNER JOIN dbo.BankAccounts ba ON t.AccountID = ba.AccountID
      

      --同样如果你将“小于”更改为“小于或等于”,则不必添加当前项:

      SELECT t.Created, t.Description, t.Credit, t.Debit, t.TransDate, t.TransactionID, ba.AccountID,
      COALESCE((SELECT SUM(isnull(Credit,0)) - SUM(isnull(Debit,0))
                                    FROM Transactions b 
                                    WHERE b.TransactionID <= t.TransactionID  
                                     and b.AccountID = t.AccountID),0)
                                       AS RunningTotal
      FROM  Transactions t 
      INNER JOIN dbo.BankAccounts ba ON t.AccountID = ba.AccountID
      

      总数应该是:(假设)起始余额:49.25

      TransDate               Credit            Debit          RunningTotal      
      ----------------------- ----------------- -------------- ----------------- 
      2011-10-08 20:14:00     NULL              12             37.25 
      2011-10-08 20:14:00     2.11              NULL           39.36            
      2011-10-07 20:14:00     42.25             NULL           81.61
      2011-10-06 20:14:00     NULL              12.25          69.36
      2011-10-05 20:14:00     31.25             NULL           100.61
      

      【讨论】:

        【解决方案5】:

        我正在尝试将此逻辑与上面的 RowNumber 和 CTE 一起使用。在我的场景中,我需要为两个字段的组合计算运行总计:SalesProdLineID 和 FiscYerPer。这是我编写的代码(在此示例中,由于基础表的大小,我将结果限制为单个月份:

         WITH RunningTotal AS
        (
           SELECT to2PN.CompanyID, REPLACE(SP.SalesProdLineID, ' Sls PL','') AS SlsPL, vo2PNQtyProd.QtyProdStock,  FP.FiscYearPer, FP.FiscPer, FP.FiscYear
              , ROW_NUMBER() OVER (ORDER BY SP.SalesProdLineID,FP.FiscYearPer  ASC) AS RowNumber
              , ( ISNULL(vo2PNQtyProd.QtyProdStock, 0)  ) AS RunningTotal
           FROM to2PN  (NOLOCK)
         JOIN to2PNProdTempl   (NOLOCK)
             ON to2PN.PNKey = to2PNProdTempl.PNKey
        JOIN timItem I  (NOLOCK)
            ON to2PNProdTempl.ItemKey = I.ItemKey
         JOIN timSalesProdLine SP (NOLOCK)
            ON I.SalesProdLineKey = SP.SalesProdLineKey
         JOIN vo2PNQtyProd   (NOLOCK)
             ON to2PNProdTempl.PNProdTemplKey=vo2PNQtyProd.PNProdTemplKey
         JOIN tglFiscalPeriod FP (NOLOCK)
            ON I.CompanyID = FP.CompanyID
                AND to2PN.ComplDateTime BETWEEN FP.StartDate AND Fp.EndDate
        WHERE I.ItemID BETWEEN '0000-0' AND '1999-9'
            AND YEAR(to2PN.[ComplDateTime]) = '2018'    --  !! COMMENT OUT for final
            AND MONTH(to2PN.[ComplDateTime]) = 5    --  !! COMMENT OUT for final
        )
        SELECT t.CompanyID, t.SlsPL, t.QtyProdStock, t.FiscYearPer, t.FiscPer, t.FiscYear
           , ( SELECT SUM(tt.RunningTotal)
               FROM RunningTotal AS tt
               WHERE tt.RowNumber <= t.RowNumber) AS RunningTotal
        FROM RunningTotal AS t
        LEFT JOIN RunningTotal AS tt ON t.RowNumber = tt.RowNumber + 1
        ORDER BY t.FiscYearPer DESC
        

        问题在于,一旦它获得了第一个 SalesProdLineID 的正确总数,它只会将该运行总数添加到下一个 SalesProdLineID。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-10-26
          • 2023-03-23
          • 1970-01-01
          • 2013-01-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多