Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.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
SQL(Oracle)中的递归计算_Sql_Oracle_Stored Procedures_Plsql_Oracle11g - Fatal编程技术网

SQL(Oracle)中的递归计算

SQL(Oracle)中的递归计算,sql,oracle,stored-procedures,plsql,oracle11g,Sql,Oracle,Stored Procedures,Plsql,Oracle11g,我很难找到将一些数据ETL到结果表中的解决方案。我认为我无法使用纯SQL实现这一点,并且由于循环,需要使用PL-SQL。sql专家能否帮助我走向正确的方向,或者提供一些解决这个问题的指针 以下是场景: 表:表A和表B 步骤: 按光盘对表A中的记录进行分组,并对“金额”字段求和。(假设任何A_CD的A_标志始终相同。)。让我们以TABLEA\u GRP的形式调用分组结果集(这不是一个表,它是一个分组查询) 从表格B中选择一行,如果B_FLG为“N”,则选择表格a_GRP中a_FLG为“N”的所有行

我很难找到将一些数据ETL到结果表中的解决方案。我认为我无法使用纯SQL实现这一点,并且由于循环,需要使用PL-SQL。sql专家能否帮助我走向正确的方向,或者提供一些解决这个问题的指针

以下是场景: 表:表A和表B

步骤:

  • 按光盘对表A中的记录进行分组,并对“金额”字段求和。(假设任何A_CD的A_标志始终相同。)。让我们以TABLEA\u GRP的形式调用分组结果集(这不是一个表,它是一个分组查询)
  • 从表格B中选择一行,如果B_FLG为“N”,则选择表格a_GRP中a_FLG为“N”的所有行。如果B_FLG为“Y”,则选择表a_GRP中的所有行
  • 从步骤2中拾取的行的第一条记录开始,计算其总金额与所选行的所有总金额之和的比率。将比率乘以B_金额,将结果金额添加到行TOTAL_AMT中,并存储在结果金额中。对步骤2中拾取的所有行重复此计算
  • 重复第2步和第3步,现在使用同一张CD上一次计算所得的金额值中的起始总金额值
  • 生成的_比率字段不需要保存,它仅用于演示目的。你会怎么做

    基本上,我想从表A和表B中获取结果_表中的数据

    有人能帮忙吗?提前非常感谢您的指导

    编辑:我添加了A_日期和B_日期以支持两个表之间的连接。为简单起见,您只需执行A.A_DATE=B.B_DATE,例如以下基本联接:

    SELECT
      A.A_CD,
      SUM(A.A_AMT) AS TOTAL_AMT,
      A.A_FLAG,
      A.A_DATE,
      B.B_ID,
      B.B_AMT,
      B.B_FLAG
    FROM
      TABLEA A
    JOIN TABLEB B
    ON A.A_DATE = B.B_DATE
    GROUP BY
      A.A_CD,
      A.A_FLAG,
      A.A_DATE,
      B.B_ID,
      B.B_AMT,
      B.B_FLAG
    ;
    

    好的,我想我找到了解决办法。这些数字与你的有点不同,但我相当肯定我的数字符合你的要求。我们可以使用单个查询(main_sql)在步骤1和2中完成所有操作。3和4必须使用递归语句(recur_sql)完成


    我想澄清一下:我是否正确理解了步骤2?第二步的结果:谢谢你的回复!是的,您的理解是正确的。好的,您在步骤3中称哪些行为“first”和“selected”?selected:结果-如果B_FLG为“N”,则选择表A_GRP中A_FLG为“N”的所有行。如果B_FLG为“Y”,则选择表a_GRP中的所有行。第一:第一行“已选”。非常感谢!正是我需要的。感谢您花了这么多时间来完成这项工作。不过有一个问题-当TABLEA中有几百万行时,这个解决方案是否比在带有游标的存储过程中更有效?我无法测试这一点,因为我还没有原始数据。计算中有一个错误:得出的_比率基于分母中的总金额。因此,任何一组B_ID的总和都将为1,以得到_比率。在当前的解决方案中,它只考虑了main_sql中总的比率。我不太确定您将如何计算得到的_比率值。您是否能够发布正在使用的PL/SQL代码?就性能而言,很难说。这实际上取决于SQL引擎如何处理这种递归。我上面的代码本质上是只使用SQL的动态编程。与许多DP算法一样,通过缓存每个结果并使用计算下一次迭代,可以使用过程解决方案改进递归解决方案。我建议创建一个合成数据集,看看哪种方法更快。
    with main_sql as (
        select  a.*,
                b.*,
                sum(a_amt) over (partition by b_id) as cd_amt,
                rank() over (partition by a_cd order by b_id) as rnk
        from   (select a_cd, a_flag, sum(a_amt) as a_amt
                from   tablea
                group  by a_cd, a_flag) a,
                tableb b
        where   a.a_flag = case when b.b_flag = 'Y' then a.a_flag else b.b_flag end
        order by b_id, a_cd
    ), 
    recur_sql (a_cd, b_id, total_amt, cd_amt, resulting_ratio, resulting_amt, rnk) as (
        select m.a_cd, 
               m.b_id, 
               m.a_amt as total_amt, 
               m.cd_amt, m.a_amt / m.cd_amt as resulting_ratio, 
               m.a_amt + (m.a_amt / m.cd_amt * m.b_amt) as resulting_amt, 
               rnk
        from   main_sql m
        where  rnk = 1
    
        union all
    
        select m.a_cd, 
               m.b_id, 
               r.resulting_amt as total_amt, 
               m.cd_amt, 
               r.resulting_amt / m.cd_amt as resulting_ratio, 
               r.resulting_amt + (r.resulting_amt / m.cd_amt * m.b_amt) as resulting_amt,
               m.rnk
        from recur_sql r,
             main_sql m
        where m.rnk > 1
        and   r.a_cd = m.a_cd
        and   m.rnk - 1 = r.rnk
    
    )
    select a_cd, b_id, total_amt, resulting_ratio, resulting_amt
    from   recur_sql
    order by 2, 1