Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Porównywanie wartości oddzielonych przecinkami z dwóch kolumn dwóch różnych tabel

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

ID1 ID2 NAZWA1 NAZWA2 2 5 WĘGLAN SODOWY, WĘGLAN SODU BEZWODNY, KWAS CYTRYNOWY WĘGLAN SODOWY, WĘGLAN SODOWY BEZWODNY 3 6 KOFEINA, PARACETAMOL PH. EUR. PARACETAMOL PH. EUR.,KOFEINA 100 10 PARACETAMOL, DEKTROMETORFAN, PSEUDOEFEDRYNA, PIRILAMINA DEKSCHLORFENIRAMINY MALEinian, PSEUDOEFEDRYNY CHLOROWODOREK 110 210 wodorotlenek sodu, węglan potasu wodorotlenek sodu, węglan potasu

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

DBFIDDLE tutaj

(kliknij link, aby zobaczyć przykładowe tabele i zapytania).




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak wysłać dowolne parametry do wyzwalacza Oracle?

  2. sqlplus:błąd podczas ładowania bibliotek współdzielonych:libsqlplus.so:nie można otworzyć pliku obiektu współdzielonego:Brak takiego pliku lub katalogu

  3. DbCommand i parametryzowany SQL, ORACLE vs SQL Server

  4. nie można zapisać danych o dużym rozmiarze za pomocą UTL_FILE.PUT_LINE

  5. Jak zobaczyć aktualną instrukcję Oracle SQL, która jest wykonywana?