2011-02-01 10 views
0

私は、文字列を持っている:Dの反復とSQL Serverの文字列の部分文字列

@TempCol = sigma_x1,sigma_x2,...,sigma_xd,XX,YY,ZZ 

私は、文字列sigma_x1,sigma_x2,...,sigma_xdを取得する部分文字列を取得したいです。それは私がdの値を知っているが、私は知らないことの部分文字列を取得する方法である1、3、20、...、など

できるように

dは、変数であります元の文字列はdです。

私はこの試みた:

@L = '' 
SET @ColumnNo = 0 
WHILE @ColumnNo <= @d 
BEGIN 
    SET @L = @L + ' ' + SUBSTRING(@TempCol, 1, CHARINDEX(',',@TempCol)-1) 
    SET @TempCol = REPLACE (@TempCol, LTRIM(RTRIM(@L)) ,'') 
    Set @ColumnNo = @ColumnNo + 1 
    PRINT @L 
END 

を私は期待した結果を取得する方法がわかりません。

+0

'@L'に初期化されたものと' @L'への最初の割り当てでは 'L'とは何ですか? –

+0

申し訳ありませんが、@ LがLではないことを意味する間違って書いています。連結しようとしていましたが、成功していませんでした。 @L = ''のように初期化されます。 – cMinor

+0

基本的に、文字列 '@TempCol = 'item1、item2、...''から最初の '@ d'アイテムを含む部分文字列を抽出します。そうですか? –

答えて

1
DECLARE @TempCol varchar(max), @d int, @p int, @Result varchar(max); 
SET @TempCol = 'item1,item2,itemA,itemB,item#,item$'; 
SET @d = 3; 

SET @p = 1; 

WHILE @d > 0 AND @p > 0 BEGIN 
    SET @p = CHARINDEX(',', @TempCol, @p); 
    IF @p > 0 SET @p = @p + 1; 
    SET @d = @d - 1; 
END; 

IF @p = 0 
    SET @Result = @TempCol 
ELSE 
    SET @Result = SUBSTRING(@TempCol, 1, @p - 2); 

SELECT @Result; 

は基本的には、ループだけを検索します最終的な位置で切断する。ループの後に部分文字列が抽出されます。

@dをあまりに大きく指定すると、結果はすべて@TempColになります。そうでない場合は、必要な数のアイテムが得られます。

1

スプリット機能が必要です(下部に表示)。

With SplitItems As 
    (
    Select Position, Value 
     , Row_Number() Over (Order By Position) As ItemNum 
    From dbo.udf_Split(@TempCol, ',') 
    ) 
Select Value 
From SplitItems 
Where ItemNum <= @d 

あなたは単にだろう与えられたポイントまで組み立てた文字列をしたい場合:

With SplitItems As 
    (
    Select Position, Value 
     , Row_Number() Over (Order By Position) As ItemNum 
    From dbo.udf_Split(@TempCol, ',') 
    ) 
Select ',' + Value 
From SplitItems 
Where ItemNum <= @d 
Order By ItemNum 
For Xml Path('') 

Split関数:

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
Create FUNCTION [dbo].[udf_Split] 
( 
    @DelimitedList nvarchar(max) 
    , @Delimiter nvarchar(2) = ',' 
) 
RETURNS TABLE 
AS 
RETURN 
    (
    With CorrectedList As 
     (
     Select Case When Left(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End 
      + @DelimitedList 
      + Case When Right(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End 
      As List 
      , Len(@Delimiter) As DelimiterLen 
     ) 
     , Numbers As 
     (
     Select TOP(Coalesce(DataLength(@DelimitedList)/2,0)) Row_Number() Over (Order By c1.object_id) As Value 
     From sys.columns As c1 
      Cross Join sys.columns As c2 
     ) 
    Select CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position 
     , Substring (
        CL.List 
        , CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen  
        , CharIndex(@Delimiter, CL.list, N.Value + 1)       
         - (CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen) 
        ) As Value 
    From CorrectedList As CL 
     Cross Join Numbers As N 
    Where N.Value <= DataLength(CL.List)/2 
     And Substring(CL.List, N.Value, CL.DelimiterLen) = @Delimiter 
    ) 
+0

動的SQLを使用しているので、このストアドプロシージャでこのUDFを使用するにはどうすればいいですか?コールしようとしましたが、エラーがありますか? ストアプロシージャでループのみを使用する方法はありますか? – cMinor

+0

@darkcminor - 動的SQLを使って正確に(そしてなぜ)?分割したUDFを頻繁に再利用できるようにパーマネントにすることができます。最初のクエリのみを構築またはアセンブルする必要があります。 – Thomas