【问题标题】:How to merge two rows by updating only NULL values in TSQL?如何通过仅更新 SQL 中的 NULL 值来合并两行?
【发布时间】:2018-11-17 11:58:23
【问题描述】:

我想合并两行数据,方法是根据其 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) 不应像上面的示例中那样硬编码,因为我有很多不同的表。

表格有很多行,但我只想合并两行(这总是两行)

你能帮我解决这个问题吗?

【问题讨论】:

  • 考虑到数据的简单性,为什么不直接查看并运行UPDATEDELETE 语句呢? UPDATE YourTable SET col2 = 2 WHERE ID = 1; DELETE FROM YourTable WHERE ID = 2;我非常怀疑这是否真的是你需要的,但你给我们的工作很少。您有足够的声誉知道您需要提供您的尝试,并且很少甚至没有解释的极少量样本数据将帮助其他人帮助您。请详细说明您在此处真正需要做什么来更新您的问题,并展示更多场景。
  • @Lamu 抱歉,请参阅我的编辑。
  • 那里仍然只有 2 行。我们需要一个大样本量。例如,如果 ID 3 的值 NULL 对应于 Col3,会发生什么情况?它是否保留NULL,因为那是前一行的值?如果 ID 4 有一个值怎么办?给我们至少 10-15 行来处理并解释预期的结果。
  • 另外,rn,不是m。 :D
  • @Larnu 我只尝试合并两行。

标签: sql-server tsql


【解决方案1】:

我现在发布这个答案,因为来自 OP 的 cmets 似乎确实推断这确实像我想象的那样简单。尽管他们的表有很多行,但他们只对更正/合并第 1 行和第 2 行的值感兴趣。由于这些行很简单,因此您可以简单地 UPDATE ID 1 的值,然后 DELETE 第 2 行.

由于只有几列,因此您可以简单地使用文字值,因为我们可以直观地看到,只有 ID 1 上的 Col2 需要更新:

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 问题下的所有 cmets,它们提供了 一些 更多(但还不够)细节。这是一个可扩展的动态 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;

【讨论】:

  • 太棒了,谢谢。您的动态 SQL 解决方案正是我想要的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-30
  • 2013-09-26
  • 1970-01-01
相关资源
最近更新 更多