2016-10-26 7 views

Antwort

4

Wenn ich gut verstehe, müssen Sie nicht einfach "," durch ein Leerzeichen ersetzen, sondern auch Duplikate auf eine intelligentere Weise entfernen.

Wenn ich diesen Ausdruck ändern mit dem Raum zu arbeiten, anstatt ‚‘ ich

select regexp_replace('A B A A C D' ,'([^ ]+)([ ]*\1)+', '\1') from dual 

erhalten, die 'A B A C D' gibt, nicht das, was Sie brauchen.

Ein Weg, um Ihr gewünschtes Ergebnis bekommen könnte die folgende, etwas komplizierter sein:

with string(s) as (select 'A B A A C D' from dual)  
    select listagg(case when rn = 1 then str end, ' ') within group (order by lev) 
    from (
      select str, row_number() over (partition by str order by 1) rn, lev 
      from (
       SELECT trim(regexp_substr(s, '[^ ]+', 1, level)) str, 
         level as lev 
        FROM string 
       CONNECT BY instr(s, ' ', 1, level - 1) > 0 
       ) 
     ) 

Mein Hauptproblem hier ist, dass ich nicht in der Lage bin einen regexp zu bauen, die für nicht benachbarte Dubletten überprüft, Daher muss ich die Zeichenfolge aufteilen, nach Duplikaten suchen und dann die nicht duplizierten Werte erneut aggregieren, wobei die Reihenfolge beibehalten wird.

Wenn Sie die Reihenfolge der Zeichen in dem Ergebnis-String nichts ausmachen, kann dies vereinfacht werden:

with string(s) as (select 'A B A A C D' from dual) 
select listagg(str, ' ') within group (order by 1) 
from (
     SELECT distinct trim(regexp_substr(s, '[^ ]+', 1, level)) as str 
      FROM string 
     CONNECT BY instr(s, ' ', 1, level - 1) > 0 
    ) 
+1

Ich musste nicht lange warten. :-) Allerdings ist die einzige Verbesserung in der äußeren Abfrage - benutze nur die Zeilen mit rn = 1. Das ist die einzige Vereinfachung, die in diesem Fall möglich ist. – mathguy

+0

@mathguy - Ich hatte das Gefühl, ich hatte zu viel Verschachtelung ... :) Immer noch zu denken, wenn einige Regexp Kombination könnte Splitting zu vermeiden, aber nicht zu viel Hoffnung ... – Aleksej

+0

Mit einer langen Auswahl Nesting wird ein Hit sein. Trotzdem kann ich die Bearbeitungszeit gegenüber der korrekten Lösung opfern. Danke –

4

Vorausgesetzt, dass Sie die Komponentenfolgen in der Reihenfolge ihres ersten Auftretens behalten wollen (und nicht sagen wir, sie alphabetisch neu zu ordnen - Ihr Beispiel ist in dieser Hinsicht schlecht gewählt, weil beide zu demselben Ergebnis führen), das Problem ist komplizierter, weil Sie auch die Reihenfolge verfolgen müssen. Dann müssen Sie für jeden Buchstaben nur das erste Vorkommen behalten - hier hilft row_number().

with 
    inputs (str) as (select 'A B A A C D' from dual) 
-- end test data; solution begins below this line 
select listagg(token, ' ') within group (order by id) as new_str 
from (
     select level as id, regexp_substr(str, '[^ ]+', 1, level) as token, 
       row_number() over ( 
          partition by regexp_substr(str, '[^ ]+', 1, level) 
          order by level) as rn 

     from inputs 
     connect by regexp_substr(str, '[^ ]+', 1, level) is not null 
    ) 
where rn = 1 
; 
+0

Ordnung ist kein Problem. wenn die 'A B A A C D' eine Variable ist, wie sie hier übergeben wird –

+0

Welche Art von Variable? (Oder meinen Sie einen Wert in einer Spalte in einer Tabelle?) Wenn es eine Bindevariable ist, zum Beispiel ': str', schreibe einfach': str', wo immer ich den Spaltennamen 'str' habe. HINWEIS - Wenn Sie dies für eine Tabelle tun müssen und die Eingabetabelle mehr als eine Zeile enthält, ist die Abfrage "Verbinden mit" etwas komplizierter. – mathguy

+0

Wenn die Reihenfolge der Token in der resultierenden Zeichenfolge nicht mit der ursprünglichen Zeichenfolge in Beziehung stehen muss, kann die Lösung die Unterabfrage für die Abfrage der äußeren Abfrage (und die Verwendung von 'row_number()') vermeiden. – mathguy

3

Xquery?

select xmlquery('string-join(distinct-values(ora:tokenize(.," ")), " ")' passing 'A B A A C D' returning content) result from dual 
+0

Was benötigt man auf seinem System, um das zu funktionieren? Ich habe es gerade auf meinem Rechner ausprobiert und die Ausgabe ist '(XMLTYPE)', nicht 'A B C D'. – mathguy

+0

wrapp arround 'xmlcast (xmlquery (...) als varchar2 (2000))' –

Verwandte Themen