2016-05-12 9 views
1

Ich möchte ListAgg verwenden und dann INSTR/REGEXPR oben verwenden, um zu verstehen, ob die resultierende Zeichenfolge eine Kombination von Zeichenfolgen hat oder nicht.Verwenden Sie Instr auf ListAGG

Beispiel

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

Ich möchte, dass sie zusammen mit LISTAGG aufzulisten und setzen INSTR dann zu sagen, wenn die LIST AGG hat sowohl "AB" und "AM"

Ergebnis wird

Appnumber   MyResult 
123    1 
345    0 

Irgendwelche Vorschläge?

Danke

+1

Hallo, - das macht nicht viel Sinn. Wollen Sie sagen, wenn appNumber 123 die Entscheidungszeichenfolgen BA und MC hat und die Verkettung BAMC ist, dann hat diese Zeichenfolge die Teilzeichenfolge AM? (Wenn dies nicht das ist, was Sie sagen, und AM muss entweder ein Wert in Decision oder ein Teilstring eines Werts in der Decision-Spalte sein, dann können Sie unabhängig von LISTAGG testen). Wenn Sie tatsächlich wollen, dass BAMC zu einer Übereinstimmung von AM führt, dann ... LISTAGG hängt von der Reihenfolge der Aggregation ab, aber Sie haben nichts darüber erwähnt. MCBA, das die andere Möglichkeit ist, enthält die Teilzeichenfolge AM nicht. – mathguy

+0

@mathguy Sie haben einen Punkt, mit dem Beispiel, das ich gab. Im wirklichen Leben wird dies jedoch nicht passieren. Sorry, um Verwirrung zu schaffen. Wenn ich LISTAGG benutze, würde ich sie mit einem Komma trennen. Und es ist kein Teilstring der Spalte. Es ist alles :) – SeeWe

Antwort

0

Ich würde überhaupt nicht mit LISTAGG verwenden; eine einfache Summe + Gruppe und ein paar Fall Ausdrücke den Job genauso gut:

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 

Dies funktioniert, indem jede der Entscheidungen zuweisen Sie für einen Wert von einer Potenz von 2 (1, sind 2 , 4, 8, usw.) und dann die sich ergebende Summe der verschiedenen Werte verwendet, um sie mit der Summe aller dieser Werte zu vergleichen. In deinem Fall suchst du nach 2 Saiten, also suchst du nach einer Summe gleich 3 (wenn du nach 3 Saiten suchst, wäre es 7 (1 + 2 + 4), 4 Saiten wären das) 15 (1 + 2 + 4 + 8) usw.).

Ob dies performanter als Tims Antwort mit listagg ist, ist eine Vermutung; Ich schlage vor, dass Sie beide Versionen testen und sehen, welche für Ihre Daten am besten funktioniert.

0

Wenn Sie nicht auf ListAgg beschränkt sind, kann ich Ihnen die andere Lösung ohne analytische Funktionen vorschlagen. Ich habe Sammlungen verwendet, damit externe Anwendungen Ihre Zustände ('AB', 'AM') in einer Funktion wie ein Array von Strings weitergeben können. Diese Funktion gibt die Ergebnismenge als geschachtelte Tabelle zurück.

vorläufige Typdeklarationen:

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

eine Funktion zu schaffen (im wirklichen Leben Sie nicht mit einer Unterabfrage 'ample_data' haben Block):

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; 

Und die Funktion sieht wie folgt aus :

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

Das ist auch eine großartige Lösung. Vielen Dank. – SeeWe