2016-03-23 4 views
1

SQL ServerのINSTR(...)およびREPLACE(REGEXP_SUBSTR(...))オラクル関数の使用を置き換える方法をお探しです。SQL ServerのREGEXP_SUBSTRを置換してください

オリジナルオラクル:私はCHARINDEXとPATINDEXを見てみましたが、何も出てパンしていない、私は、元の正規表現式はに私の頭の上にあると思い

+---------------------------------+----------------------+------------------------------+ 
|    NAME    |   OPT   |   Name2    | 
+---------------------------------+----------------------+------------------------------+ 
| AE 344592001H 6186694   | NULL     | NULL       | 
| AE_161038002_6044777   | 6044777    | 161038002     | 
| BC_VIVS_HNB011A_1WAM   | HNB011A    | VIVS       | 
| BC_56230A_30SP     | 30SP     | 56230A      | 
| CG_3334902_NETWK_ ACTLM_3334912 | NETWK_ ACTLM_3334912 | 3334902_NETWK_ ACTLM_3334912 | 
| CG_3334574_HMO1_CORACT_3334575 | HMO1_CORACT_3334575 | 3334574_HMO1_CORACT_3334575 | 
| CG_3207160_POSC_1502AH_3207161 | POSC_1502AH_3207161 | 3207160_POSC_1502AH_3207161 | 
| UH_141015_RHM     | RHM     | 141015      | 
| UH_127757_RIV     | RIV     | 127757      | 
| UH 523725 RIV     | NULL     | NULL       | 
| BS_W0055785_C500_M0005672  | C500     | W0055785      | 
+---------------------------------+----------------------+------------------------------+ 

SELECT 
     Name, 
     CASE 
      WHEN SUBSTR (NAME, 1, 2) = 'CG' 
      THEN SUBSTR (NAME,INSTR (NAME,'_',1,2)+ 1,LENGTH (NAME)) 
      ELSE REPLACE (REGEXP_SUBSTR (NAME,'_[^_]+',1,2),'_','') 
     END AS OPT, 
     CASE 
      WHEN SUBSTR (NAME, 1, 2) = 'CG' 
      THEN SUBSTR (NAME,INSTR (NAME, '_',1,1) + 1, LENGTH (NAME)) 
      ELSE REPLACE (REGEXP_SUBSTR (NAME,'_[^_]+',1,1),'_','') 
     END as Name2 

出力例を更新しましたで始まる。どのように私はSQL Serverでこのロジックを模倣することができるかについての任意のアイデア?

答えて

1

SQL Fiddle

MS SQL Serverの2014スキーマのセットアップ:1

CREATE TABLE table_name (name VARCHAR(50)); 
INSERT INTO table_name 
SELECT 'AE 344592001H 6186694' UNION ALL 
SELECT 'AE_161038002_6044777' UNION ALL 
SELECT 'BC_VIVS_HNB011A_1WAM' UNION ALL 
SELECT 'BC_56230A_30SP' UNION ALL 
SELECT 'CG_3334902_NETWK_ ACTLM_3334912' UNION ALL 
SELECT 'CG_3334574_HMO1_CORACT_3334575' UNION ALL 
SELECT 'CG_3207160_POSC_1502AH_3207161' UNION ALL 
SELECT 'UH_141015_RHM' UNION ALL 
SELECT 'UH_127757_RIV' UNION ALL 
SELECT 'UH 523725 RIV' UNION ALL 
SELECT 'BS_W0055785_C500_M0005672'; 

問合せ:

WITH Names (lvl, name, remaining, idx) AS (
    SELECT 1, 
     name, 
     name, 
     CHARINDEX('_', name) 
    FROM table_name 
    UNION ALL 
    SELECT lvl+1, 
     name, 
     SUBSTRING(remaining,idx+1,LEN(remaining)-idx), 
     CASE WHEN CHARINDEX('_', remaining, idx+1) = 0 
       THEN 0 
       ELSE CHARINDEX('_', remaining, idx+1) - idx 
       END 
    FROM Names 
    WHERE idx > 0 
) 
SELECT Name, 
     MAX(CASE WHEN lvl = 3 AND (Name LIKE 'CG%' OR idx = 0) THEN remaining 
       WHEN lvl = 3 THEN SUBSTRING(remaining, 1, idx - 1) 
       END) AS OPT, 
     MAX(CASE WHEN lvl = 2 AND (Name LIKE 'CG%' OR idx = 0) THEN remaining 
       WHEN lvl = 2 THEN SUBSTRING(remaining, 1, idx - 1) 
       END) AS Name2 
FROM Names 
GROUP BY Name 

Results

|       Name |     OPT |      Name2 | 
|---------------------------------|----------------------|------------------------------| 
|   AE 344592001H 6186694 |    (null) |      (null) | 
|   AE_161038002_6044777 |    6044777 |     161038002 | 
|     BC_56230A_30SP |     30SP |      56230A | 
|   BC_VIVS_HNB011A_1WAM |    HNB011A |       VIVS | 
|  BS_W0055785_C500_M0005672 |     C500 |      W0055785 | 
| CG_3207160_POSC_1502AH_3207161 | POSC_1502AH_3207161 | 3207160_POSC_1502AH_3207161 | 
| CG_3334574_HMO1_CORACT_3334575 | HMO1_CORACT_3334575 | 3334574_HMO1_CORACT_3334575 | 
| CG_3334902_NETWK_ ACTLM_3334912 | NETWK_ ACTLM_3334912 | 3334902_NETWK_ ACTLM_3334912 | 
|     UH 523725 RIV |    (null) |      (null) | 
|     UH_127757_RIV |     RIV |      127757 | 
|     UH_141015_RHM |     RHM |      141015 | 

クエリ2

CHARINDEX(expressionToFind, expressionToSerach[, startIndex])は言葉で_のインスタンスを検索するために使用することができます。

  • CHARINDEX('_', name)は、_の最初のインスタンスのインデックスを検出します。
  • CHARINDEX('_', name, CHARINDEX('_', name) + 1)は、_文字が2つもない場合、_の2番目のインスタンスのインデックスを検索します。0を返します。
  • CHARINDEX('_', name, CHARINDEX('_', name, CHARINDEX('_', name) + 1) + 1)は、_の文字が3つもない場合、_の3番目のインスタンスのインデックスを見つけるか、0を返します。インナーに

ネストこのあなたがこのように選択し、外側に適切なSUBSTRING Sを得るためにそれを使用することができます選択:

SELECT name, 
     CASE WHEN idx2 > idx1 AND (Name LIKE 'CG%' OR idx3 = 0)THEN SUBSTRING(name, idx2 + 1, LEN(name)) 
      WHEN idx3 > idx2 THEN SUBSTRING(name, idx2 + 1, idx3 - idx2 - 1) 
      END AS OPT, 
     CASE WHEN name LIKE 'CG%' THEN SUBSTRING(name, idx1 + 1, LEN(name)) 
      WHEN idx2 > idx1 THEN SUBSTRING(name, idx1 + 1, idx2 - idx1 - 1) 
      END AS Name2 
FROM (
    SELECT name, 
     CHARINDEX('_', name) AS idx1, 
     CHARINDEX('_', name, CHARINDEX('_', name) + 1) AS idx2, 
     CHARINDEX('_', name, CHARINDEX('_', name, CHARINDEX('_', name) + 1) + 1) AS idx3 
    FROM table_name 
) t 

Results

|       name |     OPT |      Name2 | 
|---------------------------------|----------------------|------------------------------| 
|   AE 344592001H 6186694 |    (null) |      (null) | 
|   AE_161038002_6044777 |    6044777 |     161038002 | 
|   BC_VIVS_HNB011A_1WAM |    HNB011A |       VIVS | 
|     BC_56230A_30SP |     30SP |      56230A | 
| CG_3334902_NETWK_ ACTLM_3334912 | NETWK_ ACTLM_3334912 | 3334902_NETWK_ ACTLM_3334912 | 
| CG_3334574_HMO1_CORACT_3334575 | HMO1_CORACT_3334575 | 3334574_HMO1_CORACT_3334575 | 
| CG_3207160_POSC_1502AH_3207161 | POSC_1502AH_3207161 | 3207160_POSC_1502AH_3207161 | 
|     UH_141015_RHM |     RHM |      141015 | 
|     UH_127757_RIV |     RIV |      127757 | 
|     UH 523725 RIV |    (null) |      (null) | 
|  BS_W0055785_C500_M0005672 |     C500 |      W0055785 | 
+0

ありがとうございます!信じられないほどの解決策。私は "CG"行といくつかのより良い例を含むように私の例を更新しました。あなたのソリューションはとても近いですが、CGレコードは解析されません。それについての考えは?あなたはコードが私の外にあり、解剖しようとしています。ありがとう! – russds

+0

@russds更新 - 両方の解決策が望ましい出力を出すように見えます。クエリ2はより効率的です(そしてはるかに簡単です)。 – MT0

関連する問題