列p1を更新したいのですが、p1は同じ製品です。
列p1を更新します。ここで、C1の例g6-1seは列名に存在し、行g6-1seの列p1の値nullを行g6-1srの値p1で更新します。
行1で、g6-1を読み取り、列名を検索し、存在する場合は列p1を更新します。 g6-1srを読み取って検索した後、行1の列c1の終了行に到達するまで、次にポインター、更新前の行をポイントして、列p1をnullにしません。
更新前のtbl:
+-------+-------------+-----------------------------------------------+-------+
| id | Name | C1 | P1 |
+-------+-------------+-----------------------------------------------+-------+
| 29214 | g6-1sr | g6-1, g6-1sr, g6-1se,g6-1se12,g6-1se1 | 28000 |
| 29215 | g6-1se | g6-1, g6-2, g6-1000, g6-1980, g6-1230, | null |
| 29226 | g6-1sf | g6-1, g6-2, g6-1000, g6-1980, g6-1230, | null |
| 29237 | g6-1se1 | g6-1, g6-2, g6-1000, g6-1980, g6-1230, | null |
| 29248 | g6-1se12 | g6-1, g6-2, g6-1000, g6-1980, g6-1230, | null |
| 29259 | Nkg6-1se | g6-1, g6-2, g6-1000, g6-1980, g6-1230, | null |
| 29269 | N56-1341se | N56-11, N56-1341se, N56-1100, N56-1348se, | 32000 |
| 29270 | N56-1348se | N56-11, N56-21, N56-1100, N56-2980, | null |
| 29271 | F566 1341se | g6-1, g6-2, g6-1000, g6-1980, g6-1230, | 38000 |
+-------+-------------+-----------------------------------------------+-------+
更新後のtbl:
+-------+-------------+-----------------------------------------------+-------+
| id | Name | C1 | P1 |
+-------+-------------+-----------------------------------------------+-------+
| 29214 | g6-1sr | g6-1, g6-1sr, g6-1se,g6-1se12,g6-1se1 | 28000 |
| 29215 | g6-1se | g6-1, g6-2, g6-1000, g6-1980, g6-1230, | 28000 |
| 29226 | g6-1sf | g6-1, g6-2, g6-1000, g6-1980, g6-1230, | null |
| 29237 | g6-1se1 | g6-1, g6-2, g6-1000, g6-1980, g6-1230, | 28000 |
| 29248 | g6-1se12 | g6-1, g6-2, g6-1000, g6-1980, g6-1230, | 28000 |
| 29259 | Nkg6-1se | g6-1, g6-2, g6-1000, g6-1980, g6-1230, | null |
| 29269 | N56-1341se | N56-11, N56-1341se, N56-1100, N56-1348se, | 32000 |
| 29270 | Asus N56-1348se | N56-11, N56-21, N56-1100, N56-2980, N56-2| 32000 |
| 29271 | F566 1341se | g6-1, g6-2, g6-1000, g6-1980, g6-1230, | 38000 |
+-------+-------------+-----------------------------------------------+-------+
カーソルで試してみてくださいが成功しません
チェックしてください:dbfiddle ここ
基本的に、P1がnullであるすべての行を取得し、P1値を持ち、名前がc1のようなすべての行と結合します。
LIKEの使用
UPDATE t1
SET P1 = t2.P1
FROM tbl1 t1
INNER JOIN tbl1 t2
ON t2.P1 IS NOT NULL
AND t2.c1 LIKE '%' + t1.Name + '%'
WHERE t1.P1 IS NULL;
| id|Name |C1 | P1|
|----:|:----------|:-------------------------------------------|----:|
|29214|g6-1sr |g6-1, g6-1sr, g6-1se,g6-1se12,g6-1se1 |28000|
|29215|g6-1se |g6-1, g6-2, g6-1000, g6-1980, g6-1230,|28000|
|29226|g6-1sf |g6-1, g6-2, g6-1000, g6-1980, g6-1230,| |
|29237|g6-1se1 |g6-1, g6-2, g6-1000, g6-1980, g6-1230,|28000|
|29248|g6-1se12 |g6-1, g6-2, g6-1000, g6-1980, g6-1230,|28000|
|29259|Nkg6-1se |g6-1, g6-2, g6-1000, g6-1980, g6-1230,| |
|29269|N56-1341se |N56-11, N56-1341se, N56-1100, N56-1348se, |32000|
|29270|N56-1348se |N56-11, N56-21, N56-1100, N56-2980, |32000|
|29271|F566 1341se|g6-1, g6-2, g6-1000, g6-1980, g6-1230,|38000|
dbo.SplitCompare()関数の使用
UPDATE t1
SET P1 = t2.P1
FROM tbl1 t1
INNER JOIN tbl1 t2
ON t2.P1 IS NOT NULL
AND dbo.SplitCompare(t2.C1, t1.Name) = 1
WHERE t1.P1 IS NULL;
更新
チェックしてください:dbfiddle ここ
まず、新しい関数を追加しました:[dbo]。[SplitCompare]
-------------------------------------------------------------------------------------
-- Compares each item of a coma-delimited string (without trainling spaces),
-- against @ToSearch.
--
-- Returns: (int)
--
-- 1 - @ToSearch matches some item
-- 0 - No matches found.
-------------------------------------------------------------------------------------
CREATE FUNCTION [dbo].[SplitCompare] (@List nvarchar(MAX), @ToSearch nvarchar(1024))
RETURNS int
AS
BEGIN
DECLARE @Item nvarchar(1024) = null;
DECLARE @Result int = 0;
WHILE LEN(@List) > 0
BEGIN
IF PATINDEX('%,%', @List) > 0
BEGIN
SET @Item = SUBSTRING(@List, 0, PATINDEX('%,%', @List));
SET @List = SUBSTRING(@List, LEN(@Item + ';') + 1, LEN(@List));
END
ELSE
BEGIN
SET @Item = @List;
SET @List = NULL;
END
IF RTRIM(LTRIM(@Item)) = @ToSearch -- does it match?
BEGIN
SET @Result = 1;
SET @List = '';
END
END
RETURN @Result;
END
次に、OP要件に従って、CURSORを使用してこのソリューションを実装しました。
-------------------------------------------------------------------------------------
-- Use @LimitRows just to limit the number of rows to be updated each time
-- the script is executed.
-------------------------------------------------------------------------------------
DECLARE @LimitRows int = 100;
DECLARE @Id int, @Name nvarchar(2048), @P1 int;
-- only selects rows where P1 IS NULL
DECLARE CurPrices CURSOR
FOR SELECT TOP (@LimitRows) Id, Name FROM #tbl1 WHERE P1 IS NULL;
OPEN CurPrices
FETCH NEXT FROM CurPrices INTO @Id, @Name
WHILE @@FETCH_STATUS = 0
BEGIN
SET @P1 = NULL;
-- note: top (1)
--
SELECT TOP (1) @P1 = t.P1
FROM tbl1 t
WHERE t.P1 IS NOT NULL
AND dbo.SplitCompare(t.C1, @Name) = 1
ORDER BY Id;
IF COALESCE(@P1,0) > 0
BEGIN
UPDATE #tbl1
SET P1 = @P1
WHERE Id = @Id;
IF @@ERROR <> 0
BEGIN
CLOSE CurPrices;
DEALLOCATE CurPrices;
RAISERROR('ERROR', 20, -1);
END
END
FETCH NEXT FROM CurPrices INTO @Id, @Name
END
CLOSE CurPrices;
DEALLOCATE CurPrices;
結果は最初のコマンドと同じですが、これにより、実行されるたびに影響を受ける行の数を制限できます。