SQL查询以分组期初余额值

时间:2019-05-02 15:01:05

标签: sql

我对SQL查询还比较陌生,而Stack Overflow以前通过阅读其他人的问题或回答我的特定问题为我指明了正确的方向。但是我找不到能解决我问题的任何东西。

我有两个数据表,它们已结合在一起以创建属于特定帐户的交易列表。我已经完成并工作了这一部分(可能不是最有效的编码,但据我所知)。如果需要,我可以发布代码。结果如下所示,“余额”列是在SQL查询中计算的,并且不在任何表中: enter image description here

这很好,但是我想在开始时添加一个“期初余额”行,该行将对特定日期之前该帐户中的所有记录求和,余额中将包括期初金额。我希望它看起来像这样: enter image description here

我使用的调整后代码:

SELECT
 Result.TransID,
 Result.TransDate,
 Result.Reference,
 Result.Description,
 Result.Amount,
 SUM(Result.Amount) OVER(PARTITION BY Result.ledgerRef ORDER BY 
 Result.TransID) AS 'Balance'

FROM    
(
    (SELECT 
        -1 TransID,
        NULL AS 'TransDate',
        NULL AS 'Reference',
        OB.Description,
        SUM(OB.Amount) AS 'Amount',
        SUM(OB.Amount) AS 'Balance',
        OB.LedgerRef

    FROM        
        (
            (SELECT
                -1 AS 'ID',
                MAX(T.dtm_TransDate) AS 'TransDate',
                ' ' AS 'Reference',
                'Opening Balance' AS 'Description',
                    SUM(CASE
                            WHEN LT.txt_LedgerTypeRef = 'REV' then -TD.dbl_TransDataAmount
                            WHEN LT.txt_LedgerTypeRef = 'EXP' then TD.dbl_TransDataAmount
                            WHEN LT.txt_LedgerTypeRef = 'ASS' then TD.dbl_TransDataAmount
                            WHEN LT.txt_LedgerTypeRef = 'LIA' then -TD.dbl_TransDataAmount
                            WHEN LT.txt_LedgerTypeRef = 'EQU' then -TD.dbl_TransDataAmount
                            ELSE TD.dbl_TransDataAmount
                        END) AS 'Amount',
                        LT.txt_LedgerTypeRef AS 'LedgerRef'


            FROM dbo.tbl_TransData AS TD

                JOIN dbo.tbl_Trans AS T ON T.int_Trans_ID = TD.int_TransID
                JOIN dbo.tbl_TransType AS TT ON TT.int_TransType_ID = T.int_TransTypeID
                JOIN dbo.tbl_Account AS A ON A.int_Account_ID = TD.int_AccountID
                JOIN dbo.tbl_Ledger AS L ON L.int_Ledger_ID = A.int_LedgerID
                JOIN dbo.tbl_LedgerType AS LT ON LT.int_LedgerType_ID = L.int_LedgerTypeID  

            WHERE
                T.int_BusinessID = 1
                AND T.bit_Archive <> 1
                AND T.bit_Disabled <> 1
                AND T.bit_TransDelete <> 1
                AND T.dtm_TransDate < '2019-01-01'
                AND TD.int_AccountID = 2167

            GROUP BY

                LT.txt_LedgerTypeRef,
                TD.dbl_TransDataAmount
            )

            UNION

            (SELECT
                -1 AS 'ID',
                MAX(T.dtm_TransDate) AS 'TransDate',
                ' ' AS 'Reference',
                'Opening Balance' AS 'Description',
                SUM(CASE
                        WHEN LT.txt_LedgerTypeRef = 'REV' THEN -T.dbl_TransAmount
                        WHEN LT.txt_LedgerTypeRef = 'EXP' THEN T.dbl_TransAmount
                        WHEN LT.txt_LedgerTypeRef = 'ASS' THEN T.dbl_TransAmount
                        WHEN LT.txt_LedgerTypeRef = 'LIA' THEN -T.dbl_TransAmount
                        WHEN LT.txt_LedgerTypeRef = 'EQU' THEN -T.dbl_TransAmount
                        ELSE T.dbl_TransAmount
                    END) AS 'Amount',
                    LT.txt_LedgerTypeRef AS 'LedgerRef'


            FROM dbo.tbl_Trans AS T

            JOIN dbo.tbl_TransType AS TT ON TT.int_TransType_ID = T.int_TransTypeID
            JOIN dbo.tbl_Account AS A ON A.int_Account_ID = T.int_AccountIDBank
            JOIN dbo.tbl_Ledger AS L ON L.int_Ledger_ID = A.int_LedgerID
            JOIN dbo.tbl_LedgerType AS LT ON LT.int_LedgerType_ID = L.int_LedgerTypeID

            WHERE
                T.int_BusinessID = 1
                AND T.bit_Archive <> 1
                AND T.bit_Disabled <> 1
                AND T.bit_TransDelete <> 1
                AND T.dtm_TransDate < '2019-01-01'
                AND T.int_AccountIDBank = 2167

            GROUP BY
                LT.txt_LedgerTypeRef,
                T.dbl_TransAmount
            )
        ) AS OB

    GROUP BY
        OB.Description,
        OB.LedgerRef
    )

    UNION

    (SELECT 
        TR.TransID,
        TR.TransDate,
        TR.Reference,
        TR.Description,
        TR.Amount,
        SUM(TR.amount) OVER(PARTITION BY TR.ledgerRef ORDER BY TR.TransID) AS 'Balance',
        TR.LedgerRef

    FROM    
        (
            (SELECT
                T.int_Trans_ID AS 'TransID',
                T.dtm_TransDate AS 'TransDate',
                concat(TT.txt_TransTypeCode, T.dbl_TransRef) AS 'Reference',
                TD.txt_TransDataDescription AS 'Description',
                    CASE
                        WHEN LT.txt_LedgerTypeRef = 'REV' then -TD.dbl_TransDataAmount
                        WHEN LT.txt_LedgerTypeRef = 'EXP' then TD.dbl_TransDataAmount
                        WHEN LT.txt_LedgerTypeRef = 'ASS' then TD.dbl_TransDataAmount
                        WHEN LT.txt_LedgerTypeRef = 'LIA' then -TD.dbl_TransDataAmount
                        WHEN LT.txt_LedgerTypeRef = 'EQU' then -TD.dbl_TransDataAmount
                        ELSE TD.dbl_TransDataAmount
                    END AS 'Amount',
                    LT.txt_LedgerTypeRef AS 'LedgerRef'

            FROM dbo.tbl_TransData AS TD

                JOIN dbo.tbl_Trans AS T ON T.int_Trans_ID = TD.int_TransID
                JOIN dbo.tbl_TransType AS TT ON TT.int_TransType_ID = T.int_TransTypeID
                JOIN dbo.tbl_Account AS A ON A.int_Account_ID = TD.int_AccountID
                JOIN dbo.tbl_Ledger AS L ON L.int_Ledger_ID = A.int_LedgerID
                JOIN dbo.tbl_LedgerType AS LT ON LT.int_LedgerType_ID = L.int_LedgerTypeID  

            WHERE
                T.int_BusinessID = 1
                AND T.bit_Archive <> 1
                AND T.bit_Disabled <> 1
                AND T.bit_TransDelete <> 1
                AND T.dtm_TransDate >= '2019-01-01'
                AND TD.int_AccountID = 2167
            )
            UNION
            (SELECT
                T.int_Trans_ID AS 'TransID',
                T.dtm_TransDate AS 'TransDate',
                concat(TT.txt_TransTypeCode, T.dbl_TransRef) AS 'Reference',
                T.txt_TransDescription AS 'Description',
                CASE
                    WHEN LT.txt_LedgerTypeRef = 'REV' THEN -T.dbl_TransAmount
                    WHEN LT.txt_LedgerTypeRef = 'EXP' THEN T.dbl_TransAmount
                    WHEN LT.txt_LedgerTypeRef = 'ASS' THEN T.dbl_TransAmount
                    WHEN LT.txt_LedgerTypeRef = 'LIA' THEN -T.dbl_TransAmount
                    WHEN LT.txt_LedgerTypeRef = 'EQU' THEN -T.dbl_TransAmount
                    ELSE T.dbl_TransAmount
                END AS 'Amount',
                LT.txt_LedgerTypeRef AS 'LedgerRef'

            FROM dbo.tbl_Trans AS T

            JOIN dbo.tbl_TransType AS TT ON TT.int_TransType_ID = T.int_TransTypeID
            JOIN dbo.tbl_Account AS A ON A.int_Account_ID = T.int_AccountIDBank
            JOIN dbo.tbl_Ledger AS L ON L.int_Ledger_ID = A.int_LedgerID
            JOIN dbo.tbl_LedgerType AS LT ON LT.int_LedgerType_ID = L.int_LedgerTypeID

            WHERE
                T.int_BusinessID = 1
                AND T.bit_Archive <> 1
                AND T.bit_Disabled <> 1
                AND T.bit_TransDelete <> 1
                AND T.dtm_TransDate >= '2019-01-01'
                AND T.int_AccountIDBank = 2167
            )

        ) AS TR
    )
) AS Result

这一切似乎都正常,在这里我不得不合并两个表以用于期初余额和交易,所以那里有很多联合。

结果如下:

enter image description here

仅一点,在期初余额行上,我希望“金额”为空白,但是如果我将其保留在期初余额查询之外,则结转的余额是错误的。它在代码的第17行。不确定是否可以做到。

再一次提出任何建议将不胜感激。

2 个答案:

答案 0 :(得分:1)

在没有所有表格并进行完整设置和样本填充的情况下,我可以提供以下信息...

您的INNER查询将所有交易和明细预先收集起来,然后合并为一组...,然后由外部查询将它们汇总。

我会再添加一个调整查询的方法(同样,只是指导与全部数据准备等)。

select
      … original fields and sum(…)( over/order by)
   from
      ( InnerQuery1
        UNION
        InnerQuery2 )

并更改为

select
      … original fields and sum(…)( over/order by)
   from
      ( InnerQuery1
           where TransDate > YourCutoffDate
        UNION
        InnerQuery2
           where TransDate > YourCutoffDate
        UNION
        ( select
                -- place-holder field to match the union requirements               
                -1 int_Trans_ID,
                MAX( ExistingDataDate ) AS 'TransDate',
                ' ' as 'Reference',
                'Balance Forward' as 'Description',
                SUM( CASE
                    WHEN LT.txt_LedgerTypeRef = 'REV' THEN -T.dbl_TransAmount
                    WHEN LT.txt_LedgerTypeRef = 'EXP' THEN T.dbl_TransAmount
                    WHEN LT.txt_LedgerTypeRef = 'ASS' THEN T.dbl_TransAmount
                    WHEN LT.txt_LedgerTypeRef = 'LIA' THEN -T.dbl_TransAmount
                    WHEN LT.txt_LedgerTypeRef = 'EQU' THEN -T.dbl_TransAmount
                    ELSE T.dbl_TransAmount
                END ) AS 'Amount',
                LT.txt_LedgerTypeRef AS 'LedgerRef'
            from
                . . .  
            where
                TransDate <= YourCutoffDate                   
            group by
                ?LedgerReg -- unsure per your data sources
        )
     )

在这种情况下,您始终可以根据自己的优点运行新查询以实现余额平衡,以确保使语法和聚合意义成为您想要获取的意图。通过使用WHERE子句将顶部查询限制为仅包含截止日期之后的那些,它们将是它们自己的。对于截止之前的所有交易,此新查询将预汇总到单个行(每个分类帐)中,仅留下1条记录(每个分类帐)。在交易日期使用MAX()可以确保它浮动到按日期排列的顶部,并且应该首先使用它来启动余额远期价值。

希望这很有意义,因为其余的查询已经在起作用。在这里,您实质上是在查询截止日期之前或之前的所有记录并添加到列表中。因此,请先自行构建此查询,然后调整您现有的查询以包含为其他联合。

最后清除期初余额。您具有ID = -1的受控值。使用案例/何时删除。在您的OUTERMOST查询中,更改

修订以清除期初余额金额行...

Result.Amount,
SUM(Result.Amount) OVER(PARTITION BY Result.ledgerRef ORDER BY 

case when int_trans_id < 0 then 0 else Result.Amount end Amount,
SUM(Result.Amount) OVER(PARTITION BY Result.ledgerRef ORDER BY 

答案 1 :(得分:0)

正如我在评论中提到的那样,当您包含代码时,这要容易得多,因此我们可以对其进行添加。无论如何,这是相似的随机表的答案:

SELECT SUM(T.[Value]) AS OPENING_BALANCE --Sum (addition of) all values in col [Value]
FROM 
(SELECT [Id]
      ,[Title]
      ,[Units]
      ,[Value]
  FROM [DBNAME].[dbo].[Data]) T