使用 SQL 从贷方和 运行 余额中有条件地借记

Conditional debit from credits and running balance using SQL

我在 table cryptotransactionledger

中有如下数据
id transaction_typeid transaction_type amount totalcoins
1 1 bitcoin-credit 30 30
2 2 ethereum-credit 20 50

如果我花比特币,我会在相同的 table 和 transaction_typeid 3 中放置一个新条目,如下所示,类似地,对于以太坊, transaction_typeid 4

id transaction_typeid transaction_type amount totalcoins
1 1 bitcoin-credit 30 30
2 2 etherium-credit 20 50
3 3 bitcoin-debit -10 40
4 4 etherium-debit -5 35

假设如果我在 table 中的最终数据如下所示,我将有 35 个比特币和 20 个以太坊。

id transaction_typeid transaction_type amount totalcoins
1 1 bitcoin-credit 30 30
2 2 etherium-credit 20 50
3 3 bitcoin-debit -10 40
4 4 etherium-debit -5 35
5 1 bitcoin-credit 15 50
6 2 etherium-credit 10 60
7 4 etherium-debit -5 55

在从相应的贷方中减少所有借方后,如何使用 SQL 得出低于余额的摘要

id transaction_type amount totalcoins
1 bitcoin-credit 35 35
2 etherium-credit 20 55

假设您有表 ledgercoin_types:

create table ledger (id varchar2(3) primary key, 
                 coin_type varchar2(2), 
                 amount number(5)
                 );

create table coin_types (id varchar2(2) primary key, 
                         alias varchar2(100));

这些 DML 语句代表您的“最终数据”:

insert into coin_types values (1, 'bitcoin');
insert into coin_types values (2, 'etherium');

insert into ledger values (1, 1, 30);
insert into ledger values (2, 2, 20);
insert into ledger values (3, 1, -10);
insert into ledger values (4, 2, -5);
insert into ledger values (5, 1, 15);
insert into ledger values (6, 2, 10);
insert into ledger values (7, 2, -5);

您的第一步应该是汇总金额,按您的硬币类型分组:

  select l.coin_type, 
         c.alias,
         sum(l.amount) amount_coin
    from ledger l, coin_types c
   where l.coin_type = c.id
group by l.coin_type, c.alias

然后您可以使用此 select 获得您的“totalcoins”作为累积总和,按您的 coin_type (see Oraclee Docs):

排序
   select coin_type, 
          alias, 
          amount_coin, 
          sum(amount_coin) over (order by coin_type) totalcoins 
      from(
          select l.coin_type, 
                 c.alias,
                 sum(l.amount) amount_coin
            from ledger l, coin_types c
           where l.coin_type = c.id
        group by l.coin_type, c.alias
           );

这是一个有效的 SQL-Fiddle:SQL-Fiddle

我会忘记最终结果的“交易类型”,只关注硬币本身。您的数据模型很奇怪,因为您没有单独的硬币类型列。但是您可以从 transaction_type 列中提取它。

此外,您的评论表明 totalcoins 应该是列中的最后一个值。 “比特币”是 50,而不是 35。

无论如何,您都可以使用聚合。我会建议:

select regexp_substr(transaction_type, '^[^-]+') as coin,
       sum(amount) as amount,
       max(totalcoins) keep (dense_rank first oder by id desc) as totalcoins
from cryptotransactionledger tl
group by regexp_substr(transaction_type, '^[^-]+');

Here 是一个 db<>fiddle.

我会创建一个 table 的 tran 类型

create table tran_types (
   id int primary key,
   coin_Name varchar2(100),
   op_Name varchar2(100)
   );

insert into tran_types  
select 1, 'bitcoin', 'credit' from dual union all
select 2, 'etherium','credit' from dual union all
select 3, 'bitcoin', 'debit'  from dual union all
select 4, 'etherium','debit'  from dual;

通过这种方式,您可以对交易进行分组以获得总计,并根据需要可视化总计行headers

select t.id transaction_typeid, t.coin_Name || '-' || t.op_Name transaction_type, 
    s.amount, s.total_coins
from (
  select t.coin_Name, sum(amount) amount
    , sum(sum(amount)) over(order by t.coin_Name) total_coins
  from ledger r
  join tran_types t on r.tran_type = t.id
  group by t.coin_Name
) s
join tran_types t on t.op_name = 'credit' and t.coin_Name = s.coin_Name
order by t.coin_Name;

感谢所有提出建议和不同解决方案的人。 我终于使用了下面的查询,它为我提供了预期的结果。

WITH cte1
 AS (SELECT a.*,
            CASE
              WHEN ( transaction_typeid = 1
                      OR transaction_typeid = 3 ) THEN 0
              ELSE 1
            END AS category
     FROM   cryptotransactionledger a
     ORDER  BY id),
 cte2
 AS (SELECT CASE
              WHEN ( category = 0 ) THEN 'bitcoin-credit'
              ELSE 'etherium-credit'
            END         AS transaction_type,
            Sum(amount) AS amount
     FROM   cte1 o
     GROUP  BY category),
 cte3
 AS (SELECT Row_number()
              OVER (ORDER BY c.transaction_type) AS id,
            c.*
     FROM   cte2 c) SELECT f.*,
     Sum(amount) OVER(ORDER BY f.id) AS total_coins FROM cte3 f;

Link to DB Fiddle