2012-11-09 7 views
7

2つのテーブルがあります。
別のテーブルのselect文の行の複数のタグを置き換えます。

Ans_code      Ans_Desc 
------------------------------------------- 
50000000000000005770  Enter <B><APN></B> and press Ok.  
40000000000000000164  Enter <B><ACCOUNTNAME></B> in connection name. 
40000000000000000165  Enter <B><ACCOUNTNAME></B> in <APN>. 

などに従うよう
一つはanswer_step_dtl
別ではtag_mstです。

そして、私のtag_mstは今、私の要件は、私は、タグのマストの置き換え値との回答フォームの回答テーブルを選択します。この本

TAG_CODE     TAG_NAME   TAG_VALUE 
------------------------------------------------------- 
100       <APN>   EXAMPLE.COM 
101       <ACCOUNTNAME> EXAMPLE 

のような値がありました。 ans_descに複数のタグが存在することがあります。


は私が

  • ループレコード内の複数のタグを通じて、個々のレコードからタグを取得し、その後 タグを置き換えるanswer_dtlの結果を通じてアプローチ

    1. ループを考えていました

    2. 一時テーブルに格納し、新しいtemテーブルのカーソルを開きます。

    これがアプローチですか。あるいは、これを行う簡単な方法があります。

  • +0

    同じ 'ans_desc'に2つのタグ名がある可能性はありますか? – Ben

    +0

    はい、そうでなければ可能です@ジョーのソリューションは完璧です。 –

    +0

    @Ben私は自分の質問を親切に見て更新しました。 –

    答えて

    3

    編集:@Rob van Wijkから(再帰的)CTE、inspired by a noteを使用してボーナスクエリを、(R2?)11グラムを必要とします:

    SQL> WITH data AS (
        2  SELECT ans_code, Ans_Desc, tag_name, tag_value, 
        3   row_number() OVER (partition BY ans_code ORDER BY t.rowid) no, 
        4   row_number() OVER 
        5    (partition BY ans_code ORDER BY t.rowid DESC) is_last 
        6  FROM answer_step_dtl a 
        7  JOIN tag_mst t ON a.ans_desc LIKE '%' || t.tag_name || '%' 
        8 ), n(ans_code, no, is_last, replaced) AS (
        9  SELECT ans_code, no n, is_last, 
    10   replace (ans_desc, tag_name, tag_value) replaced 
    11  FROM data 
    12  WHERE no = 1 
    13  UNION ALL 
    14  SELECT d.ans_code, d.no, d.is_last, 
    15   replace (n.replaced, d.tag_name, d.tag_value) replaced 
    16  FROM data d 
    17  JOIN n ON d.ans_code = n.ans_code 
    18  AND d.no = n.no + 1 
    19 ) 
    20 SELECT * 
    21 FROM n 
    22 WHERE is_last=1; 
    
    ANS_CODE    NO IS_LAST REPLACED 
    -------------------- -- ------- --------------------------------------- 
    40000000000000000164 1  1 Enter <B>EXAMPLE</B> in connection 
    50000000000000005770 1  1 Enter <B>EXAMPLE.COM</B> and press Ok. 
    40000000000000000165 2  1 Enter <B>EXAMPLE</B> in EXAMPLE.COM. 
    

    最初の回答:

    PL/SQL関数を使用できます。

    CREATE OR REPLACE FUNCTION replacetags(p_desc VARCHAR2) 
        RETURN VARCHAR2 IS 
        l_result LONG := p_desc; 
        l_tag_pos INTEGER := 1; 
        l_tag  tag_mst.tag_name%TYPE; 
    BEGIN 
        LOOP 
         l_tag  := regexp_substr(l_result, '<[^<]+>', l_tag_pos); 
         l_tag_pos := regexp_instr(l_result, '<[^<]+>', l_tag_pos) + 1; 
         EXIT WHEN l_tag IS NULL; 
         BEGIN 
         SELECT replace(l_result, l_tag, tag_value) 
          INTO l_result 
          FROM tag_mst 
          WHERE tag_name = l_tag; 
         EXCEPTION 
         WHEN no_data_found THEN 
          NULL; -- tag doesn't exist in tag_mst 
         END; 
        END LOOP; 
        RETURN l_result; 
    END; 
    
    SQL> SELECT ans_code, replacetags(ans_desc) 
        2 FROM answer_step_dtl; 
    
    ANS_CODE    REPLACETAGS(ANS_DESC) 
    --------------------- ---------------------------------------- 
    50000000000000005770 Enter <B>EXAMPLE.COM</B> and press Ok. 
    40000000000000000164 Enter <B>EXAMPLE</B> in connection 
    40000000000000000165 Enter <B>EXAMPLE</B> in EXAMPLE.COM. 
    
    +0

    thaks @Vincent私はこれを適用し、それを参照してください –

    +0

    感謝@ヴィンセントそれは完璧に動作しています。しかし、answer_step_dtlに60〜70ステップがあり、各ステップにいくつかのタグがある場合、それらはオーバーヘッド(オープンカーソルの問題)になります。 –

    +0

    これは、 'answer_step_dtl'の行を1回だけ読み込み、各タグに対してインデックス固有スキャンを取得します。これでOKになります。この関数は明示的なカーソルを使用しないので、開いたカーソルの問題はありません:) 11gR2を使用している場合、他のクエリを試して、データセット上で最も速いものを教えてください。 –

    1

    この試してみてください。

    select d."Ans_code",replace("Ans_Desc","TAG_NAME","TAG_VALUE") 
    from answer_step_dtl d, tag_mst m 
    where "Ans_Desc" like '%'|| "TAG_NAME" || '%' 
    


    SQL fiddle demo

    +0

    2つのタグが連続していると動作しますか? –

    +0

    私は編集してみましたが、複数のタグでは動作しません。 –

    +0

    @krshekhar: –

    関連する問題