在 ListAGG 上使用 instr

use instr on ListAGG

我想使用 ListAgg,然后在它上面使用 INSTR/REGEXPR 来了解结果字符串是否包含字符串组合。

例子

appNumber   Decision
123         AB
345         BC
123         PA
345         PA
123         AM

我想使用 LISTAGG 将它们一起列出,然后使用 INSTR 说明 LIST AGG 是否同时具有 "AB" 和 "AM"

结果将是

Appnumber         MyResult
123               1
345               0

有什么建议吗?

谢谢

我根本不会费心使用 LISTAGG;一个简单的 sum + group by 和几个 case 表达式也可以完成这项工作:

with sample_data as (select 123 appnumber, 'AB' decision from dual union all
                     select 345 appnumber, 'BC' decision from dual union all
                     select 123 appnumber, 'PA' decision from dual union all
                     select 345 appnumber, 'PA' decision from dual union all
                     select 123 appnumber, 'AM' decision from dual)
-- end of mimicking a table called "sample_data" that contains your data
select   appnumber,
         case when sum(distinct case when decision = 'AB' then 1 
                                     when decision = 'AM' then 2
                                     else 0
                                end) = 3 then 1
              else 0
         end myresult
from     sample_data
group by appnumber;

 APPNUMBER   MYRESULT
---------- ----------
       123          1
       345          0

这是通过为您正在搜索的每个决策分配一个 2 的幂值(1、2、4、8 等),然后使用不同值的总和与所有这些值的总和。在您的情况下,您正在搜索 2 个字符串,因此您正在检查等于 3 的总和(如果您正在检查是否存在 3 个字符串,则为 7 (1 + 2 + 4),4 个字符串为15 (1 + 2 + 4 + 8), 等等).

这是否比 Tim 使用 listagg 的答案更高效,这是任何人的猜测;我建议您测试两个版本,看看哪个版本最适合您的数据。

如果您不限于使用 ListAgg,我可能会建议您使用其他没有分析功能的解决方案。我使用集合让外部应用程序在类似于字符串数组的函数中传递您的状态('AB'、'AM')。此函数 returns 结果集为嵌套 table.

初步类型声明:

create or replace type t_test_states is varray(10) of varchar2(2);
create or replace type t_test_appnumbers is table of number;

创建一个函数(在现实生活中你不会有子查询块'ample_data'):

create or replace function TEST_GET_ANSWER (p_states IN t_test_states)
    return t_test_appnumbers 
  is
    v_resultset t_test_appnumbers;
  begin      
    with sample_data as (select 123 appnumber, 'AB' decision from dual union all
                         select 345 appnumber, 'BC' decision from dual union all
                         select 123 appnumber, 'PA' decision from dual union all
                         select 345 appnumber, 'PA' decision from dual union all
                         select 123 appnumber, 'AM' decision from dual)

    select appnumber bulk collect into v_resultset
      from (
            select appnumber
              from sample_data
             where decision in (select column_value from table(p_states))
             group 
                by appnumber
                 , decision     
           ) 
     group               
        by appnumber
    --the next condition ensures that appnumber has exactly ALL states
    having count(*) = (select count(column_value) from table(p_states));

    return v_resultset;
end TEST_GET_ANSWER;

使用该函数如下所示:

select * from table(test_get_answer(t_test_states('AB','AM')))
select * from table(test_get_answer(t_test_states('PH')))
select * from table(test_get_answer(t_test_states('PA')))
select * from table(test_get_answer(t_test_states()))