sql >> Database teknologi >  >> RDS >> Oracle

Sammenligning af kommaseparerede værdier fra to kolonner i to forskellige tabeller

Du kan få tabellen/tabellerne til først normal form og derefter sammenligne de forbindelser, der er gemt i hver række. Et udgangspunkt kunne være:

{1} Tokeniser hver række, og skriv tokens ind i en ny tabel. Giv hvert token dets originale ID plus et præfiks på 3 bogstaver, der angiver, hvilken tabel tokenet kom fra.{2} Gruppér rækkerne i den nye ("normaliserede") tabel efter ID, og ​​udfør en LISTAGG(). Udfør et selvtilmelding, og find matchende "token-grupper".

{1} Tokenize, opret tabel som select (CTAS)

opret tabel tokens som vælg ltrim( -- ltrim() og rtrim() fjern førende/efterfølgende mellemrum (blanks) rtrim( substr( N.wrapped , instr( N.wrapped, ',', 1, T .pos ) + 1 , ( instr( N.wrapped, ',', 1, T.pos + 1 ) - instr( N.wrapped, ',', 1, T.pos ) ) - 1 ) ) ) token, N.idfrom ( vælg ',' || navn1 || ',' som ombrudt, 'T1_' || to_char( id_t1 ) som id fra t1 -- navne pakket ind i kommaer, (tabel)_id union alle vælg ',' | | name2 || ',' , 'T2_' || to_char( id_t2 ) fra t2 ) N join (vælg niveau som pos -- (maks.) mulig position for char i et eksisterende token fra dobbeltforbindelse med niveau <=(vælg størst ( -- find den længste streng dvs. maks. position (forespørgsel T1 og T2) ( vælg max( længde( navn1 ) ) fra t1 ), ( vælg maks. ( længde( navn2 ) ) fra t2 ) ) som pos fra dual ) ) T på T.pos <=( length( N.wrapped ) - length( replace( N.wrapped, ',') ) ) - 1; 

Inspirationen til at tokenisere uden at bruge CONNECT BY kom fra dette SO-svar .

Indholdet af TOKENS-tabellen vil se nogenlunde sådan ud:

SQL> vælg * fra tokens;TOKEN ID ASCORBIC ACID T1_1 SODIUM HYDROGEN CARBONATE T1_2 CAFFEINE T1_3 PSEUDOEPHEDRINE HYDROCHLORIDE T1_4 PARACETAMOL T1_100 natriumhydroxide T1_100 sodium hydroxide T1_110 HYDROGEN CARBONATE T1_110 HYDROGEN T1_110 PEUDOEPHEDRINE HYDROCHLORIDE T1_4 PARACETAMOL T1_100 natriumhydroxide T1_100 sodium hydroxide T1_110 Natriumhydroxide T1_110 HYDROGEN T1_110 HYDROGEN SORBONAT. EUR. T2_6 CODEIN PHOSPHATE T2_7 DEXCHLORPHENIRAMINE MALEATE T2_8 DEXCHLORPHENIRAMINE MALEATE T2_10 PARACETAMOL T2_200 ...

{2} GROUP BY, LISTAGG, selv deltagelse

vælg S1.id id1, S2.id id2, S1.tokengroup_T1, S2.tokengroup_T2from ( vælg substr( id, 4, length( id ) - 3 ) id , listagg( token, ' + ' ) indenfor gruppe (rækkefølge efter token) tokengroup_T1 fra tokens gruppe efter id med substr( id, 1, 3 ) ='T1_') S1 join ( vælg substr( id, 4, length( id ) - 3 ) id , listagg( token, ' + ' ) inden for gruppe ( sorter efter token ) tokengroup_T2 fra tokens gruppe efter id med substr( id, 1, 3 ) ='T2_') S2 på S1.tokengroup_T1 =S2.tokengroup_T2;-- resultID1 ID2 TOKENGROUP_T1 TOKENLORPHE_T2 MALECH4CHINE + PSEUDOEPHEDRIN HYDROCHLORID DEXCHLORPHENIRAMINE MALEAT + PSEUDOEPHEDRIN HYDROCHLORID 110 210 kaliumcarbonat + natriumhydroxid kaliumcarbonat + natriumhydroxid 1 4 ASCORBINSYRE + PARACETARBYKAMOL + POTDROKORBYT KAMOL SYRE + PARACETAMOL + KALIUMHYDROGENCARBONAT 3 6 KAFFEIN + PARACETAMOL PH. EUR. KAFFEIN + PARACETAMOL PH. EUR.  

Når du gør tingene på denne måde, kan du få stofferne i (alfabetisk) rækkefølge, og du kan også vælge en "afgrænser", som du kan lide (vi har brugt '+') her.

ALTERNATIV

Hvis alt det ikke nytter dig, eller du synes, det er for kompliceret, så kan du prøve at bruge TRANSLATE(). I dette tilfælde vil jeg anbefale at fjerne alle mellemrum/mellemrum fra dit datasæt (i en forespørgsel - ikke ændre de originale data!) sådan:

Forespørgsel

vælg id1, id2, navn1, navn2fra ( vælg id_t1 id1 , id_t2 id2 , T1.navn1 navn1 , T2.navn2 navn2 fra T1 join T2 på oversæt (erstat( T1.navn1, ' ', '' ) , replace( T2.name2, ' ', '' ), '!' ) =translate( replace( T2.name2, ' ', '' ), replace( T1.name1, ' ', '' ), '!' )); 

Resultat

ID1 ID2 NAVN1 NAVN2 2 5 NATRIUMBRINTCARBONAT, VANHYDRIG NATRIUMCARBONAT, CITRONSYRE NATRIUMBRINTKARBONAT, VANDIG NATRIUMCARBONAT 3 6 KAFFEIN, PARACETAMOL PH. EUR. PARACETAMOL PH. EUR.,KAFFEIN 100 10 PARACETAMOL, DEXTROMETORFAN, PSEUDOEPEDRIN, PYRILAMIN DEXCHLORPHENIRAMINE MALEAT, PSEUDOEPHEDRIN HYDROCHLORID 110 210 natriumhydroxid, kaliumcarbonat natriumhydroxid,

BEMÆRK: Jeg har tilføjet følgende rækker til dine eksempeldata:

-- T1110, 'natriumhydroxid, kaliumcarbonat'-- T2210, 'natriumhydroxid, kaliumcarbonat' 211, 'kaliumhydroxid, natriumcarbonat' 

Jeg fandt ud af, at det er nemt at bruge TRANSLATE() på en måde, der giver dig "falske positiver", dvs. stofferne med id 110, 210 og 211 vil se ud til at "matche". (Med andre ord:Jeg tror ikke, at dette er det rigtige værktøj til dette job.)

DBFIDDLE her

(følg linket for at se eksempeltabellerne og forespørgslerne).




  1. Hvordan opdeles streng ved hjælp af skilletegn ved hjælp af T-SQL?

  2. JDBC Opret tabel Eksempel Brugserklæring

  3. Postgres simple 'pivot' bord

  4. VÆLGER du øverste N rækker uden ROWNUM?