最初の問題は、テーブルの列のような列に変数を割り当てることは、テーブルのその列から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;
を必要に応じて、あなたは、おそらく(各行の一意の識別子のいくつかの並べ替えを必要とするなど、それぞれの割り当てrow a row number)、各行を標準のsで分割するplit関数(または独自の関数を使用)を呼び出し、結果をピボットします。 – ZLK