Oracle - 使用当前余额计算以前的余额

问题描述 投票:0回答:1

我有2张桌子。

  1. 表TRAN有Account_no、Transaction_date和Transaction_Amount
  2. 表 BAL 有 Account_no 和 Current_balance

我想使用 BAL 表中的 current_balance 填充 TRAN 表中的帐号结果以及运行余额。 (最后一行应该有current_balance,前一行应该有之前的余额,即current_balance减去交易金额)

这两个表中的数据如下所示:

Table TRAN (1) and BAL (2)

这是我希望输出的样子:

The Output I Desire

这是我尝试使用的代码:

SELECT 
A.ACCOUNT_NO, 
A.TRANSACTION_DATE, 
A.TRANSACTION_AMOUNT, 
B.CURRENT_BALANCE - LAG(A.TRANSACTION_AMOUNT) OVER (ORDER BY A.TRANSACTION_DATE) RUNNING_BALANCE 
FROM TRAN A 
INNER JOIN BAL B ON A.ACCOUNT_NO=B.ACCOUNT_NO
WHERE A.ACCOUNT_NO='11111111';

我得到以下输出:

Query Result

我需要对查询进行哪些更改才能获得“我想要的输出”?

oracle window-functions calculated-columns
1个回答
0
投票

当您可以通过一张桌子保持运行平衡时,为什么还要保留两张桌子?

我也做了类似的事情。您可能想看看我的解决方案。


ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS';

CREATE TABLE CUSTOMERS (
CUSTOMER_ID, FIRST_NAME, LAST_NAME,IS_ACTIVE) AS 
SELECT 'E379466', 'Bonnie', 'Winterbottom','Y' FROM DUAL  UNION ALL 
SELECT 'Z098555', 'Peter', 'Clemenza','Y' FROM DUAL;


CREATE TABLE CUSTOMER_ACCOUNTS (
ACCOUNT_NUMBER,
CUSTOMER_ID, VENDOR_ID,
IS_ACTIVE) AS 
SELECT 'THVQD6M9LR7AVK', 'E379466', 1, 'Y' FROM DUAL  UNION ALL 
SELECT '0Z76WT5NTLRZPTW',
'Z098555', 1, 'Y' FROM DUAL;

create table transactions (
     transaction_id NUMBER GENERATED BY DEFAULT AS IDENTITY,
    account_number VARCHAR2(15),
    transaction_type varchar2(1) DEFAULT 'C',
    transaction_amount NUMBER(10,2),
     transaction_date DATE DEFAULT SYSDATE 
);

insert  into transactions(
account_number, transaction_type, transaction_amount, transaction_date)
SELECT '0Z76WT5NTLRZPTW', 'D', (LEVEL * 100.57), date '2023-04-02' + level * interval '1 4' day to hour from dual
          connect by level <= 5
union all
SELECT '0Z76WT5NTLRZPTW', 'C', (LEVEL * 25.26), date '2023-04-04' + level * interval '1 4' day to hour from dual
          connect by level <= 5
union all
SELECT 'THVQD6M9LR7AVK', 'D', (LEVEL * 50.10), date '2023-05-10' + level * interval '1 7' day to hour from dual
          connect by level <= 13
union all
SELECT 'THVQD6M9LR7AVK', 'D', (LEVEL * 33.11), date '2023-05-10' + level * interval '1 7' day to hour from dual
          connect by level <= 9;

CREATE OR REPLACE FUNCTION   get_customer_balance
(  i_customer_id   IN   customers.customer_id%TYPE
)
RETURN  transactions.transaction_amount%TYPE
IS
  v_balance   transactions.transaction_amount%TYPE;
BEGIN
  SELECT SUM (
                 CASE  t.transaction_type
             WHEN  'C'
             THEN  -t.transaction_amount
             ELSE  t.transaction_amount
         END 
             )
  INTO   v_balance
  FROM   customer_accounts  ca
  JOIN   transactions       t  ON  t.account_number  = ca.account_number
  WHERE  ca.customer_id  = i_customer_id  -- one customer
  OR     ca.customer_id  IS NULL;         -- all customers

  RETURN v_balance;
END  get_customer_balance;
/


CREATE OR REPLACE FUNCTION get_account_balance(
  i_account_number IN TRANSACTIONS.ACCOUNT_NUMBER%TYPE
) RETURN TRANSACTIONS.TRANSACTION_AMOUNT%TYPE
IS
  v_balance TRANSACTIONS.TRANSACTION_AMOUNT%TYPE;
BEGIN
  SELECT SUM(
           CASE transaction_type WHEN 'C' THEN -1 ELSE 1 END 
           * transaction_amount
         )
  INTO   v_balance
  FROM   transactions
  WHERE  account_number = i_account_number -- one account
  OR     i_account_number IS NULL;         -- all accounts
  RETURN v_balance;
END;
/


SELECT CA.ACCOUNT_NUMBER,
       C.FIRST_NAME,
       C.LAST_NAME, 
       CA.IS_ACTIVE,
       get_account_balance(ca.account_number) AS balance
FROM   CUSTOMER_ACCOUNTS CA
       INNER JOIN customers c
       ON ca.customer_id = c.customer_id;

/* transaction history for an account */

WITH  daily_summary  AS
(
    SELECT  
account_number,
 transaction_date
    ,    SUM (DECODE (transaction_type, 'C', transaction_amount, 0))    AS credit_total
    ,    SUM (DECODE (transaction_type, 'D', transaction_amount , 0))   AS debit_total
    FROM     transactions
    GROUP BY  account_number, transaction_date 
)
SELECT   d.*
,    SUM (debit_total - credit_total)
       OVER (ORDER BY transaction_date) AS balance_to_date
FROM    daily_summary d
WHERE account_number = 
'0Z76WT5NTLRZPTW'
ORDER BY transaction_date;

© www.soinside.com 2019 - 2024. All rights reserved.