【问题标题】:Looping through list comma separated parameter and fetch results based on the every value before comma循环遍历列表逗号分隔的参数并根据逗号之前的每个值获取结果
【发布时间】:2021-02-24 14:31:44
【问题描述】:

输入参数是用逗号分隔的 2 个 id(from_id 和 to_id)。每个 id 都必须在报告运行时进行评估。 From_id='202031,202032,202035,202041,...' To_id ='202111,202112,202135,202141,...' 应该从 _id 过滤每个记录,并在打印到日志文件时打印相应的 to_id。始终为 202031 至 202111、202032 至 202112、202035 至 202135、20241 至 202141。以下是预期的结果。

Num_ber Description person_id   person_name Rolled_To_term  From_id to_id   term_priority_to_term   max_amt_to_term
    90010001    fund1   1           abc          N           202031 202111     3                     23  
    90010001    fund1   1           abc          N           202032 202112     6                     110
    50010001    fund2   2           xyz          N           202035 202135     2                     45 
    50010001    fund2   3           efg          N           202035 202135     5                     50  

下面的过程会更新 to_id ,但 from_id 仍然是 202031 并再次循环。游标不过滤其他 frm_id。

PROCEDURE report_v1 (
    p_frm_id_list  VARCHAR2,
    p_to_id_list    VARCHAR2
) AS
exemp_log_file      utl_file.file_type;
log_msg             VARCHAR2(600);
frm_id_list       VARCHAR2(50);
frm_id_list_temp  VARCHAR2(50);
frm_id             VARCHAR2(50);
to_id_list         VARCHAR2(50);
to_id_list _temp   VARCHAR2(50);
to_id             VARCHAR2(50);   



CURSOR get_expt_info_c IS
SELECT
    code                 AS num_ber,
    desc                 AS description,
    a.term_expiration    AS exp_term,
    (select p_id from tab3 c where a.id=c.id) as person_id,
    (select p_name from tab3 c where a.id=c.id) as person_name,
    a.term_code          AS from_id,
    nvl(
        (
            SELECT DISTINCT
                'Y'
            FROM
                tab2 b
            WHERE
                    b.term_code = to_term
                AND b.id = a.id
        ), 'N'
    ) rolled_to_term,
    a.priority           AS term_priority_to_term,
    a.amount             AS max_amt_to_term
    
FROM
         tab left
    JOIN tab2 a ON code = a.code
                   AND term_code = a.term_code
WHERE
    instr(
        frm_id, a.term_code
    ) > 0;

BEGIN
    exemp_log_file := utl_file.fopen(dir,'report.csv','w');
    log_msg := 'Report header';
    utl_file.put_line(exemp_log_file,log_msg,autoflush => true );
    frm_id_list := replace(p_frm_id_list ,' ','');
    to_id_list := replace( p_ to_id_list, ' ','' );

WHILE frm_id_list IS NOT NULL LOOP
    IF instr( frm_id_list,',') > 0 THEN
        frm_id := substr(frm_id_list,1,instr(frm_id_list,',') - 1 );

        frm_id_list_temp := substr(frm_id_list,instr(frm_id_list,',' ) + 1);
    ELSE
        frm_id := frm_id_list;
        frm_id_list_temp := NULL;
    END IF;

    frm_id_list := frm_id_list_temp;
    


 WHILE to_id_list IS NOT NULL LOOP
       IF instr(to_id_list,',' ) > 0 THEN
           to_id := substr(to_id_list,1,instr(to_id_list,',' ) - 1 );

                to_id_list_temp := substr(to_id_list,instr(to_id_list,',' ) + 1 );
       ELSE
           to_id := to_id_list;
           to_id_list_temp := NULL;
       END IF;

       to_id_list := to_id_list_temp;
   FOR exemp IN get_expt_info_c LOOP
            utl_file.put_line(
                exemp_log_file,
                exemp.num_ber
                || ';'
                || exemp.description
                || ';'
                || exemp.exp_term
                || ';'
                || exemp.person_id
                || ';'
                || exemp.person_name
                || ';'
                || exemp.from_id
                || ';'
                || exemp.rolled_to_term
                || ';'
                || exemp.priority
                || ';'
                || exemp.amt
                || ';'
                || to_id,
                              autoflush => true
            );
        END LOOP;
    END LOOP;
END LOOP;

EXCEPTION
    WHEN no_data_found THEN
       NULL;
    WHEN OTHERS THEN
       EXIT;
        utl_file.fclose(exemp_log_file);
END report_v1;

表格定义和样本数据

CREATE TABLE "TAB" 
   (CODE" VARCHAR2(8 CHAR) NOT NULL ENABLE, 
    "TERM_CODE" VARCHAR2(6 CHAR) NOT NULL ENABLE, 
    "DESC" VARCHAR2(30 CHAR) NOT NULL ENABLE, 
    "DETAIL_CODE" VARCHAR2(4 CHAR) NOT NULL ENABLE, 
    "ACTIVITY_DATE" DATE NOT NULL ENABLE
)   

CODE      TERM_CODE   DESC    DETAIL_CODE   ACTIVITY_DATE
90010001  202031      fund1   aaa           09-Jun-2009    

CREATE TABLE."TAB2" 
   ("CODE" VARCHAR2(8 CHAR), 
    "ID" NUMBER(8,0), 
    "TERM_CODE" VARCHAR2(6 CHAR), 
    "ACTIVITY_DATE" DATE,    
    "TERM_EXPIRATION" VARCHAR2(6 CHAR),  
    "PRIORITY" NUMBER(2,0), 
    "AMOUNT" NUMBER(7,2) 
    )
    
CODE      ID    TERM_CODE   ACTIVITY_DATE   TERM_EXPIRATION     PRIORITY   AMOUNT
90010001  1     202031      09-Jun-2009     31-DEC-2030          3          23


CREATE TABLE "TAB3" 
   ("P_ID" NUMBER(8,0) NOT NULL ENABLE,     
    "P_NAME" VARCHAR2(60 CHAR) NOT NULL ENABLE, 
    "ACTIVITY_DATE" DATE NOT NULL ENABLE
    )
    
P_ID  P_NAME    ACTIVITY_DATE
1     abc       01-JAN-2007 

任何人都可以提出更好的方法/替代我的方法或纠正我的程序。

【问题讨论】:

    标签: sql for-loop plsql while-loop plsqldeveloper


    【解决方案1】:

    您的描述表明您将 2 个 CSV 字符串拆分为它们各自的元素,它们将拆分的元素组合成一组 2 个元素,每个元素一个。这可以在一条 sql 语句中完成:

    with parms( from_ids, to_ids) as 
         ( select '202031,202032,202035,202041'  
                , '202111,202112,202135,202141' 
             from dual 
         )
    select from_id, to_id
      from ( select regexp_substr (from_ids, '[^,]+', 1, rownum) from_id
                  , regexp_substr (to_ids, '[^,]+', 1, rownum)   to_id
                  , 1+length(from_ids)-length(replace(from_ids,',','')) cf 
                  , 1+ length(to_ids)-length(replace(to_ids,',',''))     ct 
               from parms 
               connect by level <= length (regexp_replace (from_ids, '[^,]+')) + 1
           )
    where cf=ct;
    

    如果初始字符串不包含相同数量的元素,则查询不会返回任何行。
    我不确定如何处理您的程序,因为您发布的内容无效并且除了编译错误之外没有产生任何结果。它不引用参数“from_id_list”,但使用变体“frm_id_list”(已定义)和“p_from_id_list”(未定义)。至于参数“to_id_list”,它尝试在赋值中使用它作为 LVALUE。由于它被定义为 IN 参数,因此这是不允许的。此外,该过程不引用除“log_msg”和“exempt_log_file”之外的任何局部变量。看起来您错误地发布了以前的版本。您可能想要编辑您的问题并发布正确的版本。
    但是,我确实似乎 2 WHILE 循环 a 正在尝试执行拆分和合并过程。上面的查询替换了两者。但这如何适应游标循环?

    【讨论】:

    • 感谢您发现遗漏/错误的变量。已编辑相同。查询应按 from id 过滤,并在打印到 exclude_log_file 时,应根据 cursor 的 from id 填充 to_id。如果 from id 是 202031 那么 to_id 应该是 202111 等等。
    • 进度,但请包括表格定义 (ddl) 和示例输入数据 - 作为文本,无图像,如果与该数据的预期输出不同。跨度>
    • 预期输出没有变化。
    • 好的,但是表定义和输入数据是什么?您还没有发布任何其他数字列表。选择了什么数据?
    • 表定义已更新(希望这是您所要求的)。输入数据与预期输出相似。
    【解决方案2】:

    所以,我有一个不久前建立的项目,与 github 上的这个项目几乎相同:https://github.com/DevNambi/sql-server-regex

    您可能想要下载并安装它(C# 确定性正则表达式函数不会破坏 SQL Server),然后使用 Matches 来获取您的匹配项及其值的结果集。 With 将允许这样的事情..

    SELECT S.RelevantColumns,   TRY_CONVERT(INT, Match) as ID
    FROM SourceTable S
        CROSS APPLY dbo.RegexMatches(S.IDlist, '(\d),') x
        INNER JOIN dbo.SomeOtherTable OT
            ON  OT.ID = TRY_CONVERT(INT, x.Match)
    

    当报告布局不利于迭代时,我已经这样做了几次,就像上面的光标一样。让我知道这是否有帮助。我完全不确定整个脚本的目的是什么,但希望这能提供一些关于如何实现这一点的见解?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-13
      • 1970-01-01
      • 2022-06-23
      • 2017-07-05
      • 2021-05-18
      • 1970-01-01
      • 2015-09-08
      • 2010-10-14
      相关资源
      最近更新 更多