2017-01-17 4 views
1

私はいくつかの奇妙な文字列で作業しており、それらを解析しようとしています。SQL文字列 - 操作と構文解析

例:ここに示されているようALS KICKBACK:AK:Acts1:SCErrors1:FErrors0:Overlays0

期待される最終的な結果は次のとおりです。

enter image description here

私は一緒にいくつかのコードを石畳ましたが、私はそれがすべてのシナリオで動作するか分かりません。任意の提案をいただければ幸いです。

CASE WHEN [Short Description] Like 'ALS KICKBACK:%:Acts%' THEN Left(SubString([Short Description], PatIndex('%[0-9.-]%', [Short Description]), 8000), 
    PatIndex('%[^0-9.-]%', SubString([Short Description], PatIndex('%[0-9.-]%', [Short Description]), 8000) + 'X')-1) 
WHEN [Short Description] Like 'ALS:KICKBACK:%:Acts%' THEN Left(SubString([Short Description], PatIndex('%[0-9.-]%', [Short Description]), 8000), 
    PatIndex('%[^0-9.-]%', SubString([Short Description], PatIndex('%[0-9.-]%', [Short Description]), 8000) + 'X')-1)  
    ELSE '0'END as Acts 

ありがとうございます。

+0

を必要に応じて、私は、言語の表現力の欠如と、それが義務付け剛性の純粋な機能的なスタイルのためにSQLでの些細な文字列操作を越えて何かをお勧めしません。中間変数もなく(結果として 'CHARINDEX'呼び出しが繰り返されます)。クライアントコードでこの処理を実行できない理由はありますか? – Dai

+1

また、どのDBMSを使用していますか? MS SQL Serverのように見えます。もしそうなら、T-SQLではなくスカラーUDFや組み込み.NETランタイム(SQL CLR)を使用してコードを単純化することができます。 – Dai

+0

どのDBMSを使用していますか? Postgresではかなり簡単です。 –

答えて

1

一つの方法は、クロス適用し、解析機能を使用している

オプション1:機能

Declare @YourTable table (ID int,[Short Description] varchar(max)) 
Insert Into @YourTable values 
(1,'ALS KICKBACK:AK:Acts1:SCErrors1:FErrors0:Overlays0') 

Select A.ID 
     ,[Short Description] 
     ,B.* 
From @YourTable A 
Cross Apply (
       Select Acts  = max(case when PatIndex('Acts[0-9]%' ,RetVal)>0 then replace(RetVal,'Acts' ,'') end) 
        ,SCErrors = max(case when PatIndex('SCErrors[0-9]%',RetVal)>0 then replace(RetVal,'SCErrors','') end) 
        ,FErrors = max(case when PatIndex('FErrors[0-9]%' ,RetVal)>0 then replace(RetVal,'FErrors' ,'') end) 
        ,Overlays = max(case when PatIndex('Overlays[0-9]%',RetVal)>0 then replace(RetVal,'Overlays','') end) 
       From (
         Select RetSeq = Row_Number() over (Order By (Select null)) 
           ,RetVal = LTrim(RTrim(B.i.value('(./text())[1]', 'varchar(max)'))) 
         From (Select x = Cast('<x>'+ replace((Select [Short Description] as [*] For XML Path('')),':','</x><x>')+'</x>' as xml).query('.')) as A 
         Cross Apply x.nodes('x') AS B(i) 
        ) P 
     ) B 

なし:parse関数

Declare @YourTable table (ID int,[Short Description] varchar(max)) 
Insert Into @YourTable values 
(1,'ALS KICKBACK:AK:Acts1:SCErrors1:FErrors0:Overlays0') 

Select A.ID 
     ,[Short Description] 
     ,B.* 
From @YourTable A 
Cross Apply (
       Select Acts  = max(case when PatIndex('Acts[0-9]%' ,RetVal)>0 then replace(RetVal,'Acts' ,'') end) 
        ,SCErrors = max(case when PatIndex('SCErrors[0-9]%',RetVal)>0 then replace(RetVal,'SCErrors','') end) 
        ,FErrors = max(case when PatIndex('FErrors[0-9]%' ,RetVal)>0 then replace(RetVal,'FErrors' ,'') end) 
        ,Overlays = max(case when PatIndex('Overlays[0-9]%',RetVal)>0 then replace(RetVal,'Overlays','') end) 
       From [dbo].[udf-Str-Parse](A.[Short Description],':') 
     ) B 

オプション2と両方とも返品

enter image description here


UDF

CREATE FUNCTION [dbo].[udf-Str-Parse] (@String varchar(max),@Delimiter varchar(25)) 
Returns Table 
As 
Return ( 
    with cte1(N) As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)), 
      cte2(N) As (Select Top (IsNull(DataLength(@String),0)) Row_Number() over (Order By (Select NULL)) From (Select N=1 From cte1 a,cte1 b,cte1 c,cte1 d) A), 
      cte3(N) As (Select 1 Union All Select t.N+DataLength(@Delimiter) From cte2 t Where Substring(@String,t.N,DataLength(@Delimiter)) = @Delimiter), 
      cte4(N,L) As (Select S.N,IsNull(NullIf(CharIndex(@Delimiter,@String,s.N),0)-S.N,8000) From cte3 S) 

    Select RetSeq = Row_Number() over (Order By A.N) 
      ,RetVal = LTrim(RTrim(Substring(@String, A.N, A.L))) 
    From cte4 A 
); 
--Orginal Source http://www.sqlservercentral.com/articles/Tally+Table/72993/ 
--Select * from [dbo].[udf-Str-Parse-8K]('Dog,Cat,House,Car',',') 
--Select * from [dbo].[udf-Str-Parse-8K]('John||Cappelletti||was||here','||') 
+0

@ChrisWそれは助けました –

+0

美しいジョンCappelletti。どうもありがとうございます。私はその一部に関数を使うことを考えなかった。非常に役に立ちます。 – ChrisW