【问题标题】:Conditional debit from credits and running balance using SQL使用 SQL 有条件地从贷方和运行余额中借记
【发布时间】:2021-11-18 06:48:44
【问题描述】:

我的表格中有如下数据cryptotransactionledger

id transaction_typeid transaction_type amount totalcoins
1 1 bitcoin-credit 30 30
2 2 ethereum-credit 20 50

如果我花费比特币,我会在同一张表中添加一个如下所示的新条目,其中 transaction_typeid 为 3,对于 ethereum,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

假设如果我在表格中的最终数据如下所示,我将拥有 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

【问题讨论】:

  • 比特币信用 35 作为总硬币的计算方法是什么?
  • @RahulBiswas totalcoins 只不过是每行中的总金额字段。由于比特币信用是第一行,它显示的金额字段的值相同,即 35。对于第二行,它确实金额 + 先前的总币,即 20 + 35 = 55。
  • @Serg 我已经更新了有问题的表结构以包括 id 列。

标签: sql oracle plsql


【解决方案1】:

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

此外,您的 cmets 建议 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 是一个 dbfiddle。

【讨论】:

  • 嗨,戈登,感谢您的回答,但我无法避免 transaction_typeid。我实际上试图实现的是我想从 transaction_typeid 1 中减去 transaction_typeid 3 并从 transaction_typeid 2 中减去 transaction_typeid 4 这将给出我的最终结果。一旦我们在 CTE 中得到了这个,我们就可以很容易地做累计和来计算 totalcoins 字段。
  • 嗨,戈登,如果我对 totalcoins 的评论有误导性,对不起。我最后一张表中的 Totalcoins 只不过是总金额列。这就是为什么第一行是 35(比特币信用),第二行是 35 + 20 = 55(以太坊信用)。最终的比特币信用不是我的第三张桌子上的比特币信用(1)减去比特币借方(4),对于以太坊(2-4)也是如此。
【解决方案2】:

假设您有表 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

然后您可以使用此选择将您的“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

【讨论】:

  • 感谢您的回答,但就我而言,我有 4 种不同的类型。 3 - 比特币借记卡,4 - 以太坊借记卡。在您代表我的最终数据的数据模型中,您使用 typeid 1 和 2 作为借方,这也不是我的情况,如果您查看我有问题的最终数据,它使用 3 和 4 作为借方。所以我在这里寻找的实际上是如何映射 1-3 和 2-4 以找到平衡。
【解决方案3】:

我会创建一个 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;

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

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;

【讨论】:

    【解决方案4】:

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

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-20
      • 2017-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多