sql-server - 如何通过仅更新 TSQL 中的 NULL 值来合并两行?
问题描述
我想合并两行数据,方法是根据其 ID 保留一行,并且仅在数据为 NULL 值时才更新数据。
例如,我想“合并”第 1 行和第 2 行并删除第 2 行:
从 :
ID date col1 col2 col3
---------------------------------------------------------------
1 31/12/2017 1 NULL 1
2 31/12/2015 3 2 NULL
3 31/12/2014 4 5 NULL
到:
ID date col1 col2 col3
---------------------------------------------------------------
1 31/12/2017 1 2 1
3 31/12/2014 4 5 NULL
在示例中,我想保留第 1 行,并用第 2 行中的值填充第 1 行中的 NULL 值。然后我将删除第 2 行。请参见下面我为日期列制作的代码。
UPDATE MyTable
SET
date = newdata.date
FROM
(
SELECT
date
FROM MyTable
WHERE
ID = 2
)
newdata
WHERE
ID = 1 AND MyTable.date IS NULL ;
我想在非常大的表上执行相同的操作,所以我正在寻找一种方法来自动将上述操作(或更好的解决方法?)应用于两个特定行的表的每一列。需要明确的是,列名 ( date
) 不应该像上面的例子那样被硬编码,因为我有很多不同的表。
该表有很多行,但我只想合并两行(这将始终是两行)
你能帮我解决这个问题吗?
解决方案
我现在发布了一个答案,因为 OP 的评论似乎确实推断出这确实像我认为的那样简单。尽管他们的表有很多行,但他们只对更正/合并第 1 行和第 2 行的值感兴趣。由于这些行很简单,因此您可以简单地UPDATE
输入 ID 1 的值,然后是DELETE
第 2 行。
由于只有几列,因此您可以简单地使用文字值,因为我们可以直观地看到只有Col2
ID 1 需要更新:
UPDATE YourTable
SET col2 = 2
WHERE ID = 1;
现在 ID 1 有正确的值,你可以DELETE
ID 2:
DELETE
FROM YourTable
WHERE ID = 2;
但是,如果您的数据(有点)过于简化,您可以执行以下操作。
UPDATE YT1
SET Col1 = ISNULL(YT1.Col1,YT2.Col1),
Col2 = ISNULL(YT1.Col2,YT2.Col2),
Col3 = ISNULL(YT1.Col3,YT2.Col3),
...
FROM YourTable YT1
JOIN YourTable YT2 ON YT2.ID = 2
WHERE YT1.ID = 1;
DELETE
FROM YourTable
WHERE ID = 2;
这是基于 OP 问题下的所有评论,这些评论提供了更多(但还不够)细节。这是一个可扩展的动态 SQL 解决方案,因为它为 OP 写出ISNULL
表达式。当然,如果这没有帮助,那么我再次建议他们更新他们的帖子以真正帮助我们帮助他们。无论如何,这应该是不言自明的:
CREATE TABLE YourTable (ID int,
[date] date,
col1 int,
col2 int,
col3 int,
col4 int,
col5 int);
GO
INSERT INTO YourTable
VALUES (1,'20171231',1,NULL,1 ,2 ,NULL),
(2,'20151231',3,2 ,NULL,NULL,4),
(3,'20141231',4,5 ,NULL,2 ,7);
SELECT *
FROM YourTable;
GO
DECLARE @SQL nvarchar(MAX);
DECLARE @TableName sysname = N'YourTable'
DECLARE @CopyToId int = 1;
DECLARE @DeleteID int = 2;
SET @SQL = N'UPDATE YT1' + NCHAR(10) +
N'SET ' + STUFF((SELECT N',' + NCHAR(10) +
N' ' + QUOTENAME(c.[name]) + N' = ISNULL(YT1.' + QUOTENAME(c.[name]) + N',YT2.' + QUOTENAME(c.[name]) + N')'
FROM sys.tables t
JOIN sys.columns c ON t.[object_id] = c.[object_id]
WHERE t.[name] = @TableName
AND c.name NOT IN (N'ID',N'date')
FOR XML PATH(N'')),1,6,N'') + NCHAR(10) +
N'FROM ' + QUOTENAME(@TableName) + N' YT1' + NCHAR(10) +
N' JOIN ' + QUOTENAME(@TableName) + N' YT2 ON YT2.ID = @dDeleteID' + NCHAR(10) +
N'WHERE YT1.ID = @dCopyToId;' + NCHAR(10) + NCHAR(10) +
N'DELETE' + NCHAR(10) +
N'FROM ' + QUOTENAME(@TableName) + NCHAR(10) +
N'WHERE ID = @dDeleteID;';
PRINT @SQL; --Your Best friend
EXEC sp_executesql @SQL, N'@dCopyToID int, @dDeleteID int', @dCopyToId = @CopyToId, @dDeleteID = @DeleteID;
GO
SELECT *
FROM YourTable;
GO
DROP TABLE YourTable;
推荐阅读
- python - 如何使用 HERE 中的异步矩阵路由 API v8 来获取包括交通在内的行程时间响应
- java - 如何将具有相同名称的字段添加到pdf
- jquery - 从 Bootstrap 3 转换为 4 时,导航栏中的 CSS 中断
- excel - Excel VBA 弹出形状
- powershell - Powershell - 参数集
- javascript - 当我使用“a”标签时,我的 div 中发生了变化
- python-3.x - 如何使用 L298n 用树莓派控制多个步进电机
- java - Java中的套接字不能在linux上运行,但在windows上运行
- python - 使用 Docker 和 nginx 将 Django 项目部署到 AWS EB
- python - Pycharm IDE,控制台中是否有类似ans的matlab