Tom*_*mas 10 sql-server sql-update
我在MS SQL Server中有一个表,其中"value"列中有一些空值
Group ID Value
A 1 10
A 2
A 3
A 4 40
B 1
B 2 20
B 3 30
B 4
Run Code Online (Sandbox Code Playgroud)
我想在具有第一个更高ID的同一组中更新空值,而不是null,或者如果同一组中没有任何更高,则先降低.所以结果应该是这样的.
Group ID Value
A 1 10
A 2 40
A 3 40
A 4 40
B 1 20
B 2 20
B 3 30
B 4 30
Run Code Online (Sandbox Code Playgroud)
谢谢!
您可以使用窗口版本的SUM函数来确定NULL有价值记录的孤岛以及同一组中具有较高ID的记录:
SELECT [Group], ID, Value,
SUM(CASE WHEN Value IS NULL THEN 0 ELSE 1 END) OVER
(PARTITION BY [Group] ORDER BY ID DESC) AS grp
FROM mytable
Run Code Online (Sandbox Code Playgroud)
输出:
Group ID Value grp
-----------------------
A 4 40 1
A 3 30 2
A 2 NULL 2
A 1 NULL 2
B 4 40 1
B 3 NULL 1
B 2 20 2
B 1 10 3
Run Code Online (Sandbox Code Playgroud)
您现在可以将上述查询包装在一个CTE并使用另一个查询进行CTE更新:
;WITH CTE AS (
SELECT [Group], ID, Value,
SUM(CASE WHEN Value IS NULL THEN 0 ELSE 1 END) OVER
(PARTITION BY [Group] ORDER BY ID DESC) AS grp
FROM mytable
), ToUpdate AS (
SELECT [Group], ID, Value,
MAX(Value) OVER (PARTITION BY [Group], grp) AS group_value
FROM CTE
)
UPDATE ToUpdate
SET Value = group_value
WHERE Value IS NULL
Run Code Online (Sandbox Code Playgroud)
编辑:
上面的查询不处理切片中最后一条记录的边缘情况.要处理这种情况,您可以使用以下查询:GroupNULL
;WITH CTE AS (
SELECT [Group], ID, Value,
SUM(CASE WHEN Value IS NULL THEN 0 ELSE 1 END) OVER
(PARTITION BY [Group] ORDER BY ID DESC) AS grp,
SUM(CASE WHEN Value IS NULL THEN 0 ELSE 1 END) OVER
(PARTITION BY [Group] ORDER BY ID) AS grp2
FROM mytable
), ToUpdate AS (
SELECT [Group], ID, Value,
MAX(Value) OVER (PARTITION BY [Group], grp) AS group_value,
MAX(Value) OVER (PARTITION BY [Group], grp2) AS group_value2
FROM CTE
)
UPDATE ToUpdate
SET Value = COALESCE(group_value, group_value2)
WHERE Value IS NULL
Run Code Online (Sandbox Code Playgroud)
请试试这个 -
数据生成
DECLARE @T TABLE
(
GroupCd CHAR(1),
Id INT,
Value INT
)
INSERT INTO @T
VALUES('A',1,10),
('A',2,NULL),
('A',3,NULL),
('A',4,40),
('B',1,NULL),
('B',2,20),
('B',3,30),
('B',4,NULL)
Run Code Online (Sandbox Code Playgroud)
解
UPDATE a
SET a.Value = b.Value
FROM @T a
INNER JOIN
(
SELECT a.GroupCd,a.Id,Coalesce(a.Value,z.Value,z1.Value) Value
FROM @T a
OUTER APPLY
(
SELECT TOP 1 Value
FROM @T b
WHERE a.GroupCd = b.GroupCd
AND b.Value IS NOT NULL AND a.Id < b.Id
ORDER BY Id
)z
OUTER APPLY
(
SELECT TOP 1 Value
FROM @T b
WHERE a.GroupCd = b.GroupCd
AND b.Value IS NOT NULL AND a.Id > b.Id
ORDER BY Id DESC
)z1
)b ON a.GroupCd = b.GroupCd AND a.Id = b.Id
SELECT * FROM @T
Run Code Online (Sandbox Code Playgroud)
OUTPUT
GroupCd Id Value
------- ----------- -----------
A 1 10
A 2 40
A 3 40
A 4 40
B 1 20
B 2 20
B 3 30
B 4 30
(8 rows affected)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1539 次 |
| 最近记录: |