none
カッコ内の文字列の抽出 RRS feed

  • 質問

  • ある文字列フィールドに

    以下の様なデータが

    ABCDEFG(abcdefg)

    前部もカッコ内の文字列も任意です、長さも不定です。

    この文字列の

    カッコの前の文字列と

    カッコの中の文字列と

    に別けて出力することって出来ませんでしょうか。

    カッコは半角の場合も全角の場合も有ります。

    カッコ内にカッコが有る場合も有ります、その場合は外側のカッコに囲まれている文字列を出したい。

    どなたか御指導いただけますよう宜しくお願い致します。

    2013年4月11日 10:26

回答

  • こんな感じかなぁ

    SELECT CASE WHEN CHARINDEX('(', VALUE) > 0 AND CHARINDEX(')', VALUE) > CHARINDEX('(', VALUE) THEN
               SUBSTRING(VALUE, 1, CHARINDEX('(', VALUE) - 1)
    	   ELSE
    	       VALUE
    	   END AS SOTO
         , CASE WHEN CHARINDEX('(', VALUE) > 0 AND CHARINDEX(')', VALUE) > CHARINDEX('(', VALUE) THEN
               REVERSE(SUBSTRING(REVERSE(SUBSTRING(VALUE, CHARINDEX('(', VALUE) + 1, LEN(VALUE))), CHARINDEX(')', REVERSE(SUBSTRING(VALUE, CHARINDEX('(', VALUE) + 1, LEN(VALUE)))) + 1, LEN(VALUE)))
    	   ELSE
    	       ''
    	   END AS NAKA
         , *
      FROM (SELECT 'AAA' AS VALUE
             UNION
    		SELECT 'A(B)'
    		 UNION
    		SELECT 'あ(い)'
    		 UNION
    		SELECT 'あ(い(う))'
    	   ) AS TEMP
    ;
    ただし、照合順序如何によってはダメだと思うので、そのあたりはうまい事お願いします。
    • 回答としてマーク 星 睦美 2013年4月22日 1:43
    2013年4月11日 13:05
  • 少しトリッキーかもしれませんが、考えてみました。 ただし、「.」は含まれていないというのが前提です。また、カッコは必ず存在するという仮定をしていますが、下記のコードはカッコが無い場合でも動作します。その場合、カッコ内も外もNULLを返します。

    select PARSENAME(
             STUFF(
                STUFF(VALUE, CHARINDEX('(', VALUE), 1, '.'),
                LEN(VALUE) - CHARINDEX(')', REVERSE(VALUE)) + 1, 1, '.Dummy'),
                3
                ) AS SOTO,
                
           PARSENAME(
             STUFF(
                STUFF(VALUE, CHARINDEX('(', VALUE), 1, '.'),
                LEN(VALUE) - CHARINDEX(')', REVERSE(VALUE)) + 1, 1, '.Dummy'),
                2
                ) AS NAKA
                
    FROM (VALUES ('AAA'), ('A(B)'), ('あ(い)'), ('あ(い(う))')) AS TEMP(VALUE)


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク 星 睦美 2013年4月22日 1:43
    2013年4月12日 5:53

すべての返信

  • こんな感じかなぁ

    SELECT CASE WHEN CHARINDEX('(', VALUE) > 0 AND CHARINDEX(')', VALUE) > CHARINDEX('(', VALUE) THEN
               SUBSTRING(VALUE, 1, CHARINDEX('(', VALUE) - 1)
    	   ELSE
    	       VALUE
    	   END AS SOTO
         , CASE WHEN CHARINDEX('(', VALUE) > 0 AND CHARINDEX(')', VALUE) > CHARINDEX('(', VALUE) THEN
               REVERSE(SUBSTRING(REVERSE(SUBSTRING(VALUE, CHARINDEX('(', VALUE) + 1, LEN(VALUE))), CHARINDEX(')', REVERSE(SUBSTRING(VALUE, CHARINDEX('(', VALUE) + 1, LEN(VALUE)))) + 1, LEN(VALUE)))
    	   ELSE
    	       ''
    	   END AS NAKA
         , *
      FROM (SELECT 'AAA' AS VALUE
             UNION
    		SELECT 'A(B)'
    		 UNION
    		SELECT 'あ(い)'
    		 UNION
    		SELECT 'あ(い(う))'
    	   ) AS TEMP
    ;
    ただし、照合順序如何によってはダメだと思うので、そのあたりはうまい事お願いします。
    • 回答としてマーク 星 睦美 2013年4月22日 1:43
    2013年4月11日 13:05
  • 質問には全く関係ないですが、aviator__さんのサンプルの FROM 以下はテーブル値コンストラクターを使うともっと簡単に書けますよ。(C. FROM 句で複数の値を派生テーブルとして指定する)

    FROM (VALUES ('AAA'), ('A(B)'), ('あ(い)'), ('あ(い(う))')) AS TEMP(VALUE)

    2013年4月11日 22:27
  • ありがとうございます。勉強になります。

    2013年4月12日 0:19
  • どうしても DB 側でストアドプロシージャなどを使って処理する必要があるのでしょうか?

    そうではなくて、DB からは "ABCDEFG(abcdefg)" のような文字列をそのまま取得して、その後 C# や VB.NET などのプログラム側で処置してよければ、カッコの前の文字列とカッコの中の文字列とに分けることは正規表現などを使って容易に可能だと思います。


    • 編集済み SurferOnWww 2013年4月13日 3:27 誤字訂正
    2013年4月12日 5:03
  • 少しトリッキーかもしれませんが、考えてみました。 ただし、「.」は含まれていないというのが前提です。また、カッコは必ず存在するという仮定をしていますが、下記のコードはカッコが無い場合でも動作します。その場合、カッコ内も外もNULLを返します。

    select PARSENAME(
             STUFF(
                STUFF(VALUE, CHARINDEX('(', VALUE), 1, '.'),
                LEN(VALUE) - CHARINDEX(')', REVERSE(VALUE)) + 1, 1, '.Dummy'),
                3
                ) AS SOTO,
                
           PARSENAME(
             STUFF(
                STUFF(VALUE, CHARINDEX('(', VALUE), 1, '.'),
                LEN(VALUE) - CHARINDEX(')', REVERSE(VALUE)) + 1, 1, '.Dummy'),
                2
                ) AS NAKA
                
    FROM (VALUES ('AAA'), ('A(B)'), ('あ(い)'), ('あ(い(う))')) AS TEMP(VALUE)


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    • 回答としてマーク 星 睦美 2013年4月22日 1:43
    2013年4月12日 5:53
  • 必ずカッコがあるのであれば、以下でも良いかもしれませんね。

    select LEFT(VALUE, CHARINDEX('(', VALUE) - 1) AS SOTO,
           SUBSTRING(VALUE,
                     CHARINDEX('(', VALUE) + 1,
                     LEN(VALUE) - CHARINDEX(')', REVERSE(VALUE)) - CHARINDEX('(', VALUE) ) AS NAKA
    
    FROM (VALUES ('AA(A)'), ('A(B)'), ('あ(い)'), ('あ(い(う))')) AS TEMP(VALUE)


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2013年4月12日 6:34
  • うっかりしていたのですが、解析する文字列の末尾は常に「)」なのでしょうか? であれば、もっと簡単にカッコ内の文字列は求まりますね。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2013年4月13日 5:58
  • フォーラム オペレーターの星 睦美です。
    エリック さん、投稿ありがとうございます。

    今回の質問へのコミュニティの皆さんからの返信があります。
    内容を確認して、参考になりましたら投稿者から[回答としてマーク]いただければ幸いです。

    ---

    回答者のみなさま、ありがとうございます。エリック さんの質問と同様に文字列から抽出を行う方法を探している方に参考になるスレッドに、今回は私から[回答としてマーク]をさせていただきました。

    こんごともフォーラムをよろしくお願いします。


    日本マイクロソフト株式会社 フォーラム オペレーター 星 睦美


    • 編集済み 星 睦美 2013年4月22日 1:49 回答としてマーク
    2013年4月15日 0:54