【问题标题】:Oracle LISTAGG() for querying useOracle LISTAGG() 用于查询
【发布时间】:2012-11-06 20:21:14
【问题描述】:

所以我试图利用 LISTAGG() 函数来简单地构建一个逗号分隔的列表以在基础查询中使用。列表生成工作正常,我只是应用了一个输出用于调试目的,我可以看到我的列表应该是这样的:

价值观: 'AB','AZ','BC','CA','CT','DC','FL','FO','GA','IL','KS','MA','MB ','ME','MN','MS','MT','NB','NC','NL','NOVA SCOTIA','NS','NT','NU','NY','ON','ONTARIO','OR','PE','QC','QUEBEC','QUEBEC','SASKATCHEWAN' ,'SK','TX','VT','WA','YT'

当我尝试将此列表变量传递给我的查询时,只是为了查看是否会返回任何内容,但如果我从上面(原样)复制/过去省/州列表而不是使用“v_Province” " 在我的 where 子句中,我得到了一个结果。我做错了什么?

  DECLARE
     v_PROVINCE varchar2(500);
     v_results varchar2(1000);
  BEGIn
        dbms_output.enable(1000000);  

       Select '''' || LISTAGG(STATE, ''',''') WITHIN GROUP (ORDER BY STATE) || '''' PROV 
       INTO v_PROVINCE
       from (Select distinct STATE from ADDRDATA where STATE IS NOT NULL);

   DBMS_OUTPUT.PUT_LINE('VALUES: ' || v_PROVINCE);

   Select CITY
   INTO v_results
   from VWPERSONPRIMARYADDRESS
   where state in (v_Province)
   AND ROWNUM <= 1;

   DBMS_OUTPUT.PUT_LINE(v_results);


  END;
  /

【问题讨论】:

    标签: oracle plsql oracle11g


    【解决方案1】:

    首先,如果可能的话,在一个语句中完成所有事情几乎总是更有效。

    您的第二个查询不起作用,因为您将所有内容都返回到一个字符串中。这不是 IN 语句所要求的逗号分隔列表。

    不过有一个小技巧可以解决这个问题。假设您将字符串用于两个 SELECT 语句之间的某些内容,您可以使用regexp_substr() 将您的字符串变成可用的内容。

    这样的事情会起作用;

    select city
      from vwpersonprimaryaddress
     where state in ( 
               select regexp_substr(v_province,'[^'',]+', 1, level) 
                 from dual
              connect by regexp_substr(v_province, '[^'',]+', 1, level) is not null
                      )
    

    必须将变量 v_province 更改为引用两次,例如 '''AB'',''AZ'',''BC''' 才能使其工作。

    这是working example

    【讨论】:

    • 谢谢!!我知道 oracle 解释列表值的方式可能有问题,但不太确定为什么......我从未使用过 regexp_substr() 函数,但我会进一步探索它看起来好像它会做的伎俩......
    【解决方案2】:

    您尝试执行的操作不起作用,因为IN 运算符将逗号分隔的列表视为单个值。理论上,您可以将值收集到单个字符串中,然后将字符串解析为单独的值,以便您的下一个查询可以解释它。但是,这将是一个非常糟糕的主意。

    更好的主意是使用数组将值列表从第一个查询传递到第二个查询:

    create type nt_varchar_50 as table of varchar2(10)
    /
    
    DECLARE
         v_PROVINCE nt_varchar_50;
         v_results varchar2(1000);
         cursor cur_provinces is
            Select distinct STATE from ADDRDATA where STATE IS NOT NULL;
         i pls_integer;
    BEGIN
         dbms_output.enable(1000000); 
         open cur_provinces;
         fetch cur_provinces bulk collect into v_PROVINCE;
         close cur_provinces;
    
         DBMS_OUTPUT.PUT('VALUES: ');
         for i in v_PROVINCE.first .. v_province.last loop
             if i <> 1 then
                DBMS_OUTPUT.PUT(', ');
             end if;              
             DBMS_OUTPUT.PUT(v_PROVINCE(i));
         end loop;
         DBMS_OUTPUT.PUT_LINE();
    
         Select CITY
         INTO v_results
         from VWPERSONPRIMARYADDRESS
         where state in (select * from table(v_Province))
         AND ROWNUM <= 1;
    
         DBMS_OUTPUT.PUT_LINE(v_results);
    END;
      /
    

    当然,即使这样也比最初使用单个 SQL 语句的效率要低得多。确实,如果您需要在两个查询之间进行某种不适合 SQL 的处理,或者可能需要多次使用第一个结果集时,您应该只使用这种技术。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-03
      • 1970-01-01
      相关资源
      最近更新 更多