2016-09-08 11 views
0

1つの表だけに1列の表があります。その1つの列にはカンマ区切りの値を持つ文字列が含まれています。私はテーブルから各文字列を選択しようとしています>文字列をコンマで分割して>別のテーブルに結果を挿入してください。区切り文字を使用して区切り文字を分割し、別の表に挿入する

私の最初の表には、次のようになります。

DataString 
abc,def,gh,i,jkl 
mnop,qr,stu,v,wxyz 

私は、データが次のようになりたいと思います:

Value1 Value2 Value3 Value4 Value5 
abc  def  gh  i  jkl 
mnop  qr  stu  v  wxyz 

これは、これまで私が持っているコードです:

DECLARE @valueList varchar(100) 
DECLARE @pos INT 
DECLARE @len INT 
DECLARE @value varchar(100) 
Select @valueList = DataString from [dbo].[rawdata] 


set @pos = 0 
set @len = 0 

WHILE CHARINDEX(',', @valueList, @pos+1)>0 
BEGIN 
    set @len = CHARINDEX(',', @valueList, @pos+1) - @pos 
    set @value = SUBSTRING(@valueList, @pos, @len) 

    insert into [dbo].[tempTable] (Value1) Values (@value)  

    set @pos = CHARINDEX(',', @valueList, @[email protected]) +1 
END 

私はこのコードに2つの問題があります。

問題1:- 変数@valueListに列DataStringをプルするためのselectステートメントは、それらのすべてを選択するのではなく、テーブルの最後の行をプルするだけです。

問題2: - my insert intoステートメントは、値を新しい行としてテーブルに挿入することしかできません。私は、対応する列に値を入力する方法を理解することはできません。

いずれかの問題を解決する方法についてのお手伝いがあれば幸いです。

+0

を必要に応じて、あなたは、おそらく(各行の一意の識別子のいくつかの並べ替えを必要とするなど、それぞれの割り当てrow a row number)、各行を標準のsで分割するplit関数(または独自の関数を使用)を呼び出し、結果をピボットします。 – ZLK

答えて

0

最初の問題は、テーブルの列のような列に変数を割り当てることは、テーブルのその列から1行だけを引き出すことです。現在行っているように列の各行をループしたい場合は、CURSORまたはそのような変形を使用して各行を調べる必要があります。

2番目の問題は、while文が間違っていることです。データストアにカンマがないときに停止するので、最後の値が失われています。最後の値にカンマがないので、最後の値をスキップします。あなたの現在のメソッドを使用してこれを回避する方法がありますが、私はあなたの文字列を分割する別の方法をお勧めします。

DECLARE @myTable TABLE (datastring VARCHAR(4000)); 
INSERT @myTable(datastring) 
VALUES ('abc,def,gh,i,jkl'),('mnop,qr,stu,v,wxyz'); 

DECLARE @valueList VARCHAR(4000) = '', @i INT = 1, @pos INT = 0, @len INT = 0, @value VARCHAR(100) = ''; 
IF OBJECT_ID('tempTable', 'U') IS NOT NULL DROP TABLE tempTable; 
CREATE TABLE tempTable (OriginalDataString VARCHAR(4000), stringVal VARCHAR(255), valNum INT); 

DECLARE curs CURSOR FOR 
SELECT datastring 
FROM @myTable; 

OPEN curs; 
FETCH NEXT FROM curs INTO @valueList; 
WHILE @@FETCH_STATUS = 0 BEGIN 
    SELECT @pos = 0, @len = 0, @i = 1; 
    WHILE 1 = 1 
    BEGIN 
     SET @len = ISNULL(NULLIF(CHARINDEX(',', @valueList, @pos+1), 0) - @pos, LEN(@valueList)); 
     SET @value = SUBSTRING(@valueList, @pos, @len); 

     INSERT tempTable(OriginalDataString, stringVal, valNum) 
     VALUES (@valueList, @value, @i); 

     IF CHARINDEX(',', @valueList, @pos+1) = 0 
      BREAK; 

     SET @pos = CHARINDEX(',', @valueList, @[email protected]) + 1; 
     SET @i += 1; 
    END 
    FETCH NEXT FROM curs INTO @valueList; 
END 
CLOSE curs; 
DEALLOCATE curs; 

SELECT MAX(CASE WHEN valNum = 1 THEN stringVal END) val1 
    , MAX(CASE WHEN valNum = 2 THEN stringVal END) val2 
    , MAX(CASE WHEN valNum = 3 THEN stringVal END) val3 
    , MAX(CASE WHEN valNum = 4 THEN stringVal END) val4 
    , MAX(CASE WHEN valNum = 5 THEN stringVal END) val5 
FROM tempTable 
GROUP BY OriginalDataString; 

これは、あなたのテーブル内の各datastringを取得するには、カーソルを使用して、カーソル内の各値を入れ、(あなたが文字列の末尾に到達したときにループ休憩)値を得るためにそれらをループして、VAL1を選択、val2、val3、val4、val5を返します。

しかし、カーソルとwhileループを使用するのではなく、再帰的なCTEを使用することをお勧めします(すでに組み込み済みの分割関数)。

例えば、

DECLARE @myTable TABLE (datastring VARCHAR(4000)); 
INSERT @myTable(datastring) 
VALUES ('abc,def,gh,i,jkl'),('mnop,qr,stu,v,wxyz'); 

WITH CTE AS (
    SELECT datastring 
     , SUBSTRING(datastring, 1, ISNULL(NULLIF(CHARINDEX(',', datastring), 0) - 1, LEN(datastring))) sString 
     , NULLIF(CHARINDEX(',', datastring), 0) cIndex 
     , 1 Lvl 
    FROM @myTable T 
    UNION ALL 
    SELECT datastring 
     , SUBSTRING(datastring, cIndex + 1, ISNULL(NULLIF(CHARINDEX(',', datastring, cIndex + 1), 0) - 1 - cIndex, LEN(datastring))) 
     , NULLIF(CHARINDEX(',', datastring, cIndex + 1), 0) 
     , Lvl + 1 
    FROM CTE 
    WHERE cIndex IS NOT NULL) 
SELECT MAX(CASE WHEN Lvl = 1 THEN sString END) val1 
    , MAX(CASE WHEN Lvl = 2 THEN sString END) val2 
    , MAX(CASE WHEN Lvl = 3 THEN sString END) val3 
    , MAX(CASE WHEN Lvl = 4 THEN sString END) val4 
    , MAX(CASE WHEN Lvl = 5 THEN sString END) val5 
    --, datastring OriginalDataString 
FROM CTE 
GROUP BY datastring; 
+0

これはとても助けになりました!ありがとうございました! –

0
Declare @YourTable table (DataString varchar(250)) 
Insert Into @YourTable values 
('abc,def,gh,i,jkl'), 
('mnop,qr,stu,v,wxyz') 

Select A.* 
     ,Value1=B.Pos1 
     ,Value2=B.Pos2 
     ,Value3=B.Pos3 
     ,Value4=B.Pos4 
     ,Value5=B.Pos5 
From @YourTable A 
Cross Apply (Select * from [dbo].[udf-Str-Parse-Row](A.DataString,',')) B 

戻り

DataString   Value1 Value2 Value3 Value4 Value5 
abc,def,gh,i,jkl abc  def  gh  i  jkl 
mnop,qr,stu,v,wxyz mnop qr  stu  v  wxyz 

その後UDF

CREATE FUNCTION [dbo].[udf-Str-Parse-Row] (@String varchar(max),@Delimeter varchar(10)) 
--Usage: Select * from [dbo].[udf-Str-Parse-Row]('Dog,Cat,House,Car',',') 
--  Select * from [dbo].[udf-Str-Parse-Row]('John Cappelletti',' ') 
--  Select * from [dbo].[udf-Str-Parse-Row]('id26,id46|id658,id967','|') 

Returns Table 

As 

Return (
    SELECT Pos1 = xDim.value('/x[1]','varchar(250)') 
      ,Pos2 = xDim.value('/x[2]','varchar(250)') 
      ,Pos3 = xDim.value('/x[3]','varchar(250)') 
      ,Pos4 = xDim.value('/x[4]','varchar(250)') 
      ,Pos5 = xDim.value('/x[5]','varchar(250)') 
      ,Pos6 = xDim.value('/x[6]','varchar(250)') 
      ,Pos7 = xDim.value('/x[7]','varchar(250)') 
      ,Pos8 = xDim.value('/x[8]','varchar(250)') 
      ,Pos9 = xDim.value('/x[9]','varchar(250)') 
    FROM (Select Cast('<x>' + Replace(@String,@Delimeter,'</x><x>')+'</x>' as XML) as xDim) A 
) 
関連する問題