2017-04-25 2 views
0

Können Sie mir bitte sagen, ob es eine alternative Funktion gibt, die ich für REGEXP_LIKE verwenden kann?Alternative zu REGEXP_LIKE in Orakel

Ich habe folgende Situation:

Names: 
ID NAME 
1 Alex 
2 Jim 
3 Tom 

Invoices: 
ID Amount Name_IDs 
1 100 1;2; 
2 200 2;3; 

Wanted output: 
Invoice_ID Names  Amount: 
1   Alex;Jim; 100 
2   Jim;Tom; 200 

Ich weiß, dass das Datenbankmodell nicht ganz technisch richtig ist, aber jetzt eine Abfrage für diesen mit REGEXP_LIKE Ich verwende in einem listagg() die Namen hinzufügen , aber die Leistung ist sehr, sehr langsam.

SELECT inv.id as invoice_id, 
     SELECT listagg(n.name,';') WITHIN GROUP (ORDER BY NULL) from names where REGEXP_LIKE(inv.names, '(^|\W)' || n.name || '(\W|$) 'as names 
     inv.amount as amount 
from invoices inv; 

Können Sie mir bitte eine Idee geben, wie Sie diese Abfrage verbessern können?

Vielen Dank!

+0

Wenn Sie Leistung wollen, speichern Sie die Daten auf SQLish Weise - eine 'InvoiceNames' Tabelle mit einer Zeile pro Rechnung und pro Name. –

+0

Und selbst wenn ich das tun kann, wie kann ich alle Namen in einer Spalte speichern? – codi05ro

Antwort

1

Wenn Sie einen Index auf Ihrem names Tisch haben, dann sollte dies schneller sein:

select i.id, 
     i.amount, 
     (select listagg(n.name, ';') within group(order by null) 
      from (select trim(regexp_substr(str, '[^;]+', 1, level)) ASPLIT 
        from (select i.name_ids as str from dual) 
       connect by regexp_substr(str, '[^;]+', 1, level) is not null) t 
      join names n 
      on n.id = t.asplit) 
    from invoices i; 

das heißt erste Teil von Name_IDs und kommen Sie mit dem names Tisch.

+0

Sehr nützlich! Vielen Dank! Es hilft! – codi05ro

1

Ich schlage vor, dass Sie Ihr Datenmodell wie folgt aus, um etwas zu ändern:

NAMES: 
ID_NAMES NAME 
10  Alex 
20  Jim 
30  Tom 

INVOICES: 
ID_INVOICE Amount 
1   100 
2   200 

INVOICE_NAMES: 
ID_INVOICE ID_NAME 
1   10 
1   20 
2   20 
2   30 

Best of luck.