Oracle PL SQL过程,用于将值从父级分解为子级

时间:2013-02-14 19:27:21

标签: oracle stored-procedures plsql cursor dynamic-sql

我正在处理我有

的案例
  1. 产品的父子层次结构:[最高级别]原材料 RM >正在进行的工作 WIP >最终产品 EP [最低级别]
  2. 特定周最终产品的订单
  3. 预测特定周的原材料正在进行的工作的值
  4. 我的目标是根据这些孩子的订单数量,将特定周的特定RM或WIP的预测值分解为该特定周的该RM或WIP的部分或全部子EP。

    这只是意味着如果我有一个RM,比如RM1,它有3个子EP,比如说EP1,EP2和EP3 ..而且我对第2周的RM1预测值为1000,那么我的目标就是拆分根据每个EP的计算或指定百分比分布,将此预测分为3个部分。

    用户可以选择使用哪种方法获取百分比分配:

    1. 计算 :用户说,根据第10到第15桶的订单(从现在开始的第10周)将RM1预测值分解为EP1和EP2从现在开始的日期到第16周)。因此,我们分别从第10周到第15周每桶计算EP1和EP2的总订单,并按如下方式计算百分比分布:EP1订单/(EP1 + EP2订单)* 100%和(EP2订单)/(EP1 + EP2订单)* 100%分别。

    2. 指定 :用户说,EP1为20%,EP2为50%,EP3为10%

    3. 然后我们根据我们计算或得到的百分比,将每个EP的第2周RM1预测值除以1000,并将其作为第2周EP的预测值存储在同一个表中。

      选择分解的方法与parent_id,child_id,子女的百分比,开始桶的开始日期,(结束桶+ 1)的开始日期一起存储在另一个表中

      我有以下表格:

      1. 产品,用于存储产品信息并维护父子层次结构(原材料>正在进行的工作>最终产品)
      2. 订单,用于存储最低层次结构的订单(最终产品)。
      3. 预测值,用于存储特定周的产品的预测值(数字)
      4. 分解方法,预测表最初存储层次结构的较高级别(原材料)的特定周的产品的预测值。该值按其​​子级别(某些最终产品)进行分解,并存储在预测表本身中。 分解方法存储使用方法的方法 分解 child 的预测值 这个孩子的百分比分布多少钱。
      5. 日期信息日期维度,包含有关特定日期所在周的开始日期(必须是星期六)和结束日期的信息
      6. 我在这里发布了我的数据模型:https://stackoverflow.com/a/14881277/891424这里是我迄今为止编写的一个函数和几个过程:

        查找与给定存储桶对应的周开始日期的功能

        CREATE OR REPLACE FUNCTION get_week_start_date(v_bucket_num IN NUMBER)
          RETURN DATE
        IS
          week_start_date DATE;
        BEGIN
          SELECT (TRUNC(SYSDATE+2, 'IW')-2) + ((v_bucket_num-1) * 7)
          INTO week_start_date FROM dual;
          RETURN week_start_date;
        END;
        

        返回给定父级的所有子EP的过程

        CREATE OR REPLACE PROCEDURE get_eps(
          v_parent IN NUMBER,
          v_children_of_parent OUT SYS_REFCURSOR
        )
        AS
          v_children SYS_REFCURSOR;
        BEGIN
          OPEN v_children_of_parent FOR
          SELECT id, name FROM (
            SELECT
              CONNECT_BY_ISLEAF isleaf, p.id, p.name
            FROM
              inf_product p
            WHERE p.level_code = 'EP'
              START WITH id = 1
              CONNECT BY PRIOR id = parent_id
            )
          WHERE isleaf = 1;
        END;
        

        执行预测值分解的程序(不完整)

        CREATE OR REPLACE PROCEDURE inf_disaggregate(v_parent_id IN NUMBER, v_bucket_start IN NUMBER, v_bucket_end IN NUMBER)
        IS
          /* Parent Product ID from input */
          v_parent_prod_id NUMBER;
        
          /* All the children of parent specified in the input */
          child_cursor  SYS_REFCURSOR;
            child_id    NUMBER;
            child_name  VARCHAR2(40);
        
          /* Forecast Bucket Info */
          vbucket_start NUMBER;
          vbucket_end NUMBER;
          vbucket_diff NUMBER;    -- loop over vbucket_diff + 1
        
          /* Date corresponding to input buckets */
          vbucket_start_date DATE;
          vbucket_end_date DATE;
        
          /* Exceptions */
          invalid_bucket EXCEPTION;
          PRAGMA EXCEPTION_INIT( invalid_bucket, -20001 );
        BEGIN
          v_parent_prod_id := v_parent_id;
        
          vbucket_start := v_bucket_start;
          vbucket_end := v_bucket_end;
          vbucket_diff := vbucket_end - vbucket_start;
        
          IF vbucket_diff < 0 THEN
            RAISE_APPLICATION_ERROR( -20001, 'Bucket numbers not in the correct order' );
          END IF;
        
          IF vbucket_start < 1 OR vbucket_start > 26 OR vbucket_end < 1 OR vbucket_end > 26 THEN
            RAISE_APPLICATION_ERROR( -20001, 'Bucket value must be within 1 to 26' );
          END IF;
        
          /* Get first day of the week corresponding to the buckets */
          vbucket_start_date := get_week_start_date(vbucket_start);
          vbucket_end_date   := get_week_start_date(vbucket_end);
        
          DBMS_OUTPUT.PUT_LINE(vbucket_start);
          DBMS_OUTPUT.PUT_LINE(vbucket_end);
          DBMS_OUTPUT.PUT_LINE(vbucket_diff);
          DBMS_OUTPUT.PUT_LINE(vbucket_start_date);
          DBMS_OUTPUT.PUT_LINE(vbucket_end_date);
        
          /* Get all child EPs for the specified parent */
          get_eps(v_parent => v_parent_prod_id, v_children_of_parent => child_cursor);
        
          LOOP 
            FETCH child_cursor
            INTO  child_id, child_name;
            EXIT WHEN child_cursor%NOTFOUND;
            DBMS_OUTPUT.PUT_LINE(child_id || ' | ' || child_name);
          END LOOP;
          CLOSE child_cursor;
        EXCEPTION
          WHEN invalid_bucket
          THEN
            DBMS_OUTPUT.PUT_LINE(SUBSTR(SQLERRM, 1 , 80));
        END;
        /
        

        运行程序

        SET SERVEROUTPUT ON;
        CALL inf_disaggregate(5, 10, 12);
        

        问题1:如何创建包或程序来完成此任务?

        问题2:如何摆脱SYS_REFCURSOR并改用动态sql? (我可能也应该摆脱child_name,因为只有ID才能满足所有目的)

        问题3 :如何获取分解方法以及 指定 ,百分比作为用户输入?

0 个答案:

没有答案