【问题标题】:use instr on ListAGG在 ListAGG 上使用 instr
【发布时间】:2016-09-09 00:17:47
【问题描述】:

我想使用 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

有什么建议吗?

谢谢

【问题讨论】:

  • 嗨,这没有多大意义。你是说,如果 appNumber 123 有决策字符串 BA 和 MC,并且串联是 BAMC,那么这个字符串是否有子字符串 AM? (如果这不是您所说的,并且 AM 必须是 Decision 列中的值或 Decision 列中值的子字符串,那么您可以独立于 LISTAGG 进行测试)。如果实际上您希望 BAMC 产生 AM 匹配,那么... LISTAGG 取决于聚合顺序,但您没有提及任何相关内容。另一种可能的 MCBA 不包含子字符串 AM。
  • @mathguy 你有道理,我举的例子。然而在现实生活中这不会发生。很抱歉造成混乱。同样使用 LISTAGG,我会用逗号分隔它们。它不是列的子字符串。这就是全部:)

标签: regex oracle plsql oracle11g listagg


【解决方案1】:

我根本不会费心使用 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 的答案更高效,这是任何人的猜测;我建议您测试这两个版本,看看哪一个最适合您的数据。

【讨论】:

    【解决方案2】:

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

    初步类型声明:

    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()))
    

    【讨论】:

    • 这也是一个很好的解决方案。谢谢。
    猜你喜欢
    • 2013-03-10
    • 1970-01-01
    • 1970-01-01
    • 2017-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-25
    相关资源
    最近更新 更多