2017-09-14 4 views
0

私はOracle関数をかなり新しく使用しています。Oracle PL/SQL - 2つの文字列間で一致する単語を特定して抽出する

COL_Aの文字列とCOL_Bの文字列を比較する関数を探していたら、文字列内の一致する単語がCOL_Cに出力されました。

  • COL_A = ‘Microsoft Office’COL_B = ‘Windows Microsoft’、従って COL_Cに予想される結果は、したがってCOL_Cで 予想結果が‘Microsoft Office’
  • COL_A = ‘Microsoft Office’COL_B = ‘Microsoft Windows'、従って 期待される結果になるであろう‘Microsoft’
  • COL_A = ‘Microsoft Office’COL_B = ‘Microsoft Office’、あろうCOL_C‘Microsoft’
  • COL_A = ‘Microsoft Office’COL_B = ‘Outlook’、したがって、COL_Cで期待 結果がNULL

だろう私は、要件(Count sequential matching words in two strings oracle)が、しかし、この関数は一致する単語の数を出力し、ほぼ満たす機能を見つけたと分類のみ(私の目的のために、順序は無関係であり、理想的には表示される一致する単語が好きです)。

CREATE OR REPLACE FUNCTION STR_WORD_MATCH(
    P_STR1 IN VARCHAR2, 
    P_STR2 IN VARCHAR2) 
RETURN NUMBER 
IS 
L_STR1 VARCHAR2(4000) := P_STR1; 
L_STR2 VARCHAR2(4000) := P_STR2; 
L_RES NUMBER DEFAULT 0; 
L_DEL_POS1 NUMBER; 
L_DEL_POS2 NUMBER; 
L_WORD1 VARCHAR2(1000); 
L_WORD2 VARCHAR2(1000); 
BEGIN 
LOOP 
    L_DEL_POS1 := INSTR(L_STR1,' '); 
    L_DEL_POS2 := INSTR(L_STR2,' '); 
    CASE L_DEL_POS1 
    WHEN 0 THEN 
    L_WORD1 := L_STR1; 
    L_STR1 := ''; 
    ELSE 
    L_WORD1 := SUBSTR(L_STR1,1,L_DEL_POS1 - 1); 
    END CASE; 
    CASE L_DEL_POS2 
    WHEN 0 THEN 
    L_WORD2 := L_STR2; 
    L_STR2 := ''; 
    ELSE 
    L_WORD2 := SUBSTR(L_STR2,1,L_DEL_POS2 - 1); 
    END CASE; 
    EXIT 
WHEN (L_WORD1 <> L_WORD2) OR ((L_WORD1 IS NULL) OR (L_WORD2 IS NULL)); 
    L_RES := L_RES + 1; 
    L_STR1 := SUBSTR(L_STR1,L_DEL_POS1 + 1); 
    L_STR2 := SUBSTR(L_STR2,L_DEL_POS2 + 1); 
END LOOP; 
RETURN L_RES; 
END; 

いつもどんな助けでも大歓迎です。

答えて

0

これは1つのクエリで行うことができますが、構文を単純化するために、単語を分割するための短い関数を作成しました。次の私は、この機能を使用してlistagg()

select rn, max(c1) c1, max(c2) c2, 
     listagg(t2.column_value, ' ') within group (order by rn, c1, c2) common 
    from (select rownum rn, c1, c2 from t) t 
    cross join table(split(c1)) t1 
    left join table(split(c2)) t2 on t2.column_value = t1.column_value 
    group by rn 

機能:

create or replace function split(i_str in varchar2) 
    return sys.odcivarchar2list pipelined is 
begin 
    for i in 1..length(' '||regexp_replace(i_str, '[^ ]+')) loop 
    pipe row (regexp_substr(i_str, '[^ ]+', 1, i)); 
    end loop; 
end; 

例:

with t (c1, c2) as (
    select 'Microsoft Office', 'Windows Microsoft' from dual union all 
    select 'Microsoft Office', 'Microsoft Office' from dual union all 
    select 'Microsoft Office', 'Microsoft Windows' from dual union all 
    select 'Microsoft Office', 'Outlook' from dual) 
select rn, max(c1) c1, max(c2) c2, 
     listagg(t2.column_value, ' ') within group (order by rn, c1, c2) common 
    from (select rownum rn, c1, c2 from t) t 
    cross join table(split(c1)) t1 
    left join table(split(c2)) t2 on t2.column_value = t1.column_value 
    group by rn 

結果:

 RN C1    C2    COMMON 
---------- ---------------- ----------------- ----------------- 
     1 Microsoft Office Windows Microsoft Microsoft 
     2 Microsoft Office Microsoft Office Microsoft Office 
     3 Microsoft Office Microsoft Windows Microsoft 
     4 Microsoft Office Outlook 
関連する問題