Możesz uzyskać tabele w pierwszej normalnej postaci, a następnie porównać związki, które są przechowywane w każdym wierszu. Punktem wyjścia może być:
{1} Tokenizuj każdy wiersz i zapisz tokeny w nowej tabeli. Nadaj każdemu tokenowi jego oryginalny identyfikator plus trzyliterowy prefiks wskazujący, z której tabeli pochodzi token.{2} Pogrupuj wiersze nowej („znormalizowanej”) tabeli według identyfikatora i wykonaj funkcję LISTAGG(). Wykonaj samodzielne dołączenie i znajdź pasujące „grupy tokenów”.
{1} Tokenize, utwórz tabelę jako wybierz (CTAS)
utwórz tokeny tabeli jako select ltrim( -- ltrim() i rtrim() usuń początkowe/końcowe spacje (spacje) rtrim( substr( N.wrapped , instr( N.wrapped, ',', 1, T .poz ) + 1 , ( instr( N.wrapped, ',', 1, T.poz + 1 ) - instr( N.wrapped, ',', 1, T.poz ) ) - 1 ) ) token, N.idfrom ( wybierz ',' || name1 || ',' jako opakowane, 'T1_' || to_char(id_t1 ) jako id od t1 - nazwy opakowane w przecinki, (tabela)_id union all wybierz ',' | | name2 || ',' , 'T2_' || to_char( id_t2 ) z t2 ) N join ( wybierz poziom jako poz -- (max) możliwa pozycja znaku w istniejącym tokenie z dual connect według poziomu <=( wybierz największy ( -- znajdź najdłuższy ciąg tj. max pozycję (zapytanie T1 i T2) ( wybierz max( length( name1 ) ) from t1 ) , ( select max( length( length( name2) ) from t2 ) ) jako pos z dual ) ) T on T.pos <=( length( N.wrapped ) - length( replace( N.wrapped, ',') ) ) - 1;
Inspiracją do tokenizacji bez użycia CONNECT BY była ta odpowiedź na SO .
Zawartość tabeli TOKENS będzie wyglądać mniej więcej tak:
SQL> wybierz * z tokenów;TOKEN ID KWAS ASKORBOWY T1_1 WĘGLAN SODU T1_2 KOFEINA T1_3 CHLOROWODOREK PSEUDOEFEDRYNY T1_4 PARACETAMOL T1_100 Wodorotlenek sodu T1_110 WODOROTLENEK POTASU. EUR. T2_6 KODEINA FOSFORAN T2_7 DEKSCHLORFENIRAMINY MALEinian T2_8 DEKSCHLORFENIRAMINY MALEinian T2_10 PARACETAMOL T2_200 ...
{2} GROUP BY, LITAGG, samodzielne dołączanie
wybierz S1.id id1, S2.id id2, S1.tokengroup_T1, S2.tokengroup_T2from ( wybierz substr( id, 4, length( id ) - 3 ) id , listagg( token, ' + ' ) w ciągu group ( uporządkowanie według tokena ) tokengroup_T1 z tokenów group by id posiadające substr( id, 1, 3 ) ='T1_') S1 join ( select substr( id, 4, length( id ) - 3 ) id , listagg( token, ' + ' ) w obrębie grupy ( kolejność według tokena ) tokengroup_T2 z grupy tokenów według id posiadającego substr( id, 1, 3 ) ='T2_') S2 na S1.tokengroup_T1 =S2.tokengroup_T2;-- resultID1 ID2 TOKENGROUP_T1 TOKENGROUP_T2 4 10 DEXCHLORP + PSEUDOEFEDRYNY CHLOROWODOREK DEXCHLORPENIRAMINY MALEinian + PSEUDOEFEDRYNY CHLOROWODOREK 110 210 węglan potasu + wodorotlenek sodu węglan potasu + wodorotlenek sodu 1 4 KWAS ASKORBINOWY + PARACETAMOL + WĘGLAN POTASU ASKORBIN KWAS + PARACETAMOL + WĘGLAN POTASU 3 6 KOFEINA + PARACETAMOL PH. EUR. KOFEINA + PARACETAMOL PH. EUR.
Robiąc to w ten sposób, możesz uporządkować substancje w (alfabetycznej) kolejności, a także wybrać „ogranicznik”, który Ci się podoba (użyliśmy tutaj „+”).
ALTERNATYWNE
Jeśli to wszystko jest dla ciebie bezużyteczne lub uważasz, że jest to zbyt skomplikowane, możesz spróbować użyć funkcji TRANSLATE(). W takim przypadku zalecam usunięcie wszystkich spacji/spacji ze zbioru danych (w zapytaniu – nie zmiana oryginalnych danych!) na przykład:
Zapytanie
wybierz id1, id2, nazwa1, nazwa2z ( wybierz id_t1 id1 , id_t2 id2 , T1.nazwa1 nazwa1 , T2.nazwa2 nazwa2 z T1 dołącz do T2 podczas translate( replace( T1.nazwa1, ' ', '' ) , replace( T2.nazwa2, ' ', '' ), '!' ) =translate( replace( T2.nazwa2, ' ', '' ), replace( T1.nazwa1, ' ', '' ), '!' ));
Wynik
UWAGA: Do przykładowych danych dodałem następujące wiersze:
-- T1110, „wodorotlenek sodu, węglan potasu”-- T2210, „wodorotlenek sodu, węglan potasu” 211, „wodorotlenek potasu, węglan sodu”
Zauważyłem, że łatwo jest używać TRANSLATE() w sposób, który daje „fałszywe trafienia”, tj. substancje o identyfikatorach 110, 210 i 211 będą „pasować”. (Innymi słowy:nie sądzę, żeby to było odpowiednie narzędzie do tej pracy.)
(kliknij link, aby zobaczyć przykładowe tabele i zapytania).