Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle SQL:从字段分隔的记录分隔的字符串列分析事务金额_Sql_Oracle - Fatal编程技术网

Oracle SQL:从字段分隔的记录分隔的字符串列分析事务金额

Oracle SQL:从字段分隔的记录分隔的字符串列分析事务金额,sql,oracle,Sql,Oracle,我在oracle sql表中有两列,其中许多重要的事务信息以一种不太容易检索的方式存储。数据集有两列trxn_a和trxn_b trxn_a: 2019-01-25~现金存款~5000美元~John Doe#2019-01-26~现金存款~1000美元~John Doe# trxn_b: 2019-01-25~现金存款~3000美元~John Doe#2019-01-25~现金存款~1500美元~John Doe#2019-01-26~现金存款~100美元~John Doe#2019-01-26

我在oracle sql表中有两列,其中许多重要的事务信息以一种不太容易检索的方式存储。数据集有两列trxn_a和trxn_b

trxn_a:

2019-01-25~现金存款~5000美元~John Doe#2019-01-26~现金存款~1000美元~John Doe#

trxn_b:

2019-01-25~现金存款~3000美元~John Doe#2019-01-25~现金存款~1500美元~John Doe#2019-01-26~现金存款~100美元~John Doe#2019-01-26~现金存款~800美元~John Doe#2019-01-26~现金存款~100美元~John Doe#

正如您看到的,字段由
~
分隔,记录由
#
分隔。可以有任意数量的事务(因此,单元格中可以有任意数量的
#

上面列出的数据只是两列(即两个单元格)中的一条数据记录

我的目标是将这些数据转换成多行,每行都是按日期计算的
总和(trxn\u amount)
。请参见以下所需输出:

 date, trxn_amt_a, trxn_amt_b
 2019-01-25, 5000, 4500
 2019-01-26, 1000, 1000
我尝试了
INSTR
SUBSTR
函数,但这对于处理这种数据结构中的变量来说并不强大。另外,我不知道如何:

  • 解析日期、交易金额
  • 按日期和日期列出的总金额
  • 然后将单元格分解成不同的行

  • 使用
    REGEXP\u SUBSTR
    拆分
    上的记录。此外,我不知道您如何在op中添加另一列,因为您在输入中没有。只需
    Replace(字符串“~cash-deposit~”、“,”下面的“)


    这是一个复杂的问题。下面是我如何进行的一步一步的描述


    第一部分是使用
    #
    分隔符将每个值拆分为行。为此,我们使用
    REGEXP\u SUBSTR()
    以及
    connectby
    来生成递归

    select trim(regexp_substr(trxn_a,'[^#]+', 1, level) ) trxn_a, level
    from mytable
    connect by regexp_substr(trxn_a, '[^#]+', 1, level) is not null
    

    然后,我们需要将每个结果值解析为列。只需使用一系列
    REGEXP\u SUBSTR()
    即可完成此操作。需要特别注意包含金额值的列,该列包含非数字字符(
    “$5000”
    ):需要删除无效字符,以便以后可以将该值视为数字

    注意:出于您的目的,您实际上不需要从值中恢复所有4列(日期和金额足够);我将显示所有列,以防您需要访问另一列

    select
        'ta' src,
        regexp_substr(trxn_a,'[^~]+', 1, 1) tdate,
        regexp_substr(trxn_a,'[^~]+', 1, 2) ttype,
        replace(regexp_substr(trxn_a,'[^$~]+', 1, 3), ',', '') tamount,
        regexp_substr(trxn_a,'[^~]+', 1, 4) tuser
    from (
        select trim(regexp_substr(trxn_a,'[^#]+', 1, level) ) trxn_a, level
        from mytable
        connect by regexp_substr(trxn_a, '[^#]+', 1, level) is not null
    )
    

    源表中的每一列(
    trxn_a
    trxn_b
    )都必须单独处理,因为每个值都会生成随机数目的记录。结果可以
    UNION
    ed,然后外部查询执行条件聚合:

    最后一个问题:

    with t as (
        select
            'ta' src,
            regexp_substr(trxn_a,'[^~]+', 1, 1) tdate,
            regexp_substr(trxn_a,'[^~]+', 1, 2) ttype,
            replace(regexp_substr(trxn_a,'[^$~]+', 1, 3), ',', '') tamount,
            regexp_substr(trxn_a,'[^~]+', 1, 4) tuser
        from (
            select trim(regexp_substr(trxn_a,'[^#]+', 1, level) ) trxn_a, level
            from mytable
            connect by regexp_substr(trxn_a, '[^#]+', 1, level) is not null
        )
        union all
        select
            'tb' src,
            regexp_substr(trxn_b,'[^~]+', 1, 1) tdate,
            regexp_substr(trxn_b,'[^~]+', 1, 2) ttype,
            replace(regexp_substr(trxn_b,'[^$~]+', 1, 3), ',', '') tamount,
            regexp_substr(trxn_b,'[^~]+', 1, 4) tuser
        from (
            select trim(regexp_substr(trxn_b,'[^#]+', 1, level) ) trxn_b, level
            from mytable
            connect by regexp_substr(trxn_b, '[^#]+', 1, level) is not null
        )
    )
    select
        tdate, 
        SUM(DECODE(src, 'ta', tamount, 0)) trxn_amt_a,
        SUM(DECODE(src, 'tb', tamount, 0)) trxn_amt_b
    from t
    group by tdate;
    
    根据您的测试数据,产生:

    TDATE       TRXN_AMT_A  TRXN_AMT_B
    2019-01-25  5000        4500
    2019-01-26  1000        1000
    

    哇,我觉得你很痛。我希望这不是你的设计?可能可以用一些正则表达式来解。是的。不是我的设计。事实上,这就是数据如何以xml格式存储在节点的单元格中。我必须从这里取出来,trxn_a和trxn_b是输入表中的两列,因此在输出表中,我喜欢这个解决方案。我唯一在想的是,我们是否能在任何情况下避免工会。
    TDATE       TRXN_AMT_A  TRXN_AMT_B
    2019-01-25  5000        4500
    2019-01-26  1000        1000