Reputation: 6732
I would like to merge two rows of data, by keeping a row based on its ID and only updating data if it is a NULL value.
As an example I want to "merge" row 1 and 2 and delete row 2:
From :
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
To:
ID date col1 col2 col3
---------------------------------------------------------------
1 31/12/2017 1 2 1
3 31/12/2014 4 5 NULL
In the example I want to keep row 1, and fill NULL values in row 1 by values that are in row 2. Then I will delete row 2. See below the code I have made for the date column.
UPDATE MyTable
SET
date = newdata.date
FROM
(
SELECT
date
FROM MyTable
WHERE
ID = 2
)
newdata
WHERE
ID = 1 AND MyTable.date IS NULL ;
I would like to perform the same operation on very large tables so I'm looking for a way to apply the above operation automatically (or a better workaround?) to every column of a table for two specific rows.
To be clear, the column name (date
) shouldn't be hardcoded as in the above example as I have plenty of different tables.
The table has many rows but I only want to merge two rows (this will always be two rows)
Could you help me with this ?
Upvotes: 0
Views: 508
Reputation: 95554
I'm posting this an an answer now, as the comments from the OP do seem to infer this really is as simple as I thought it wasn't. Although their table has a lot of rows, they are only interested in correcting/merging the values of row 1 and 2. As these rows are simplistic then you can simply UPDATE
the value of ID 1, and then DELETE
row 2.
As there's only a few columns, then you could simply use literal values, as we can visually see that only Col2
on ID 1 needs to be updated:
UPDATE YourTable
SET col2 = 2
WHERE ID = 1;
Now ID 1 has the correct value, you can DELETE
ID 2:
DELETE
FROM YourTable
WHERE ID = 2;
You could, however, do the following, if you're data is (a little) over simplified.
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;
This is based on all the comments under the OP's question, that give some more (but not enough) detail. This is a dynamic SQL solution that is scalable, as it writes out the ISNULL
expressions for the OP. Of course, if this doesn't help then once again I have the suggest they update their post to actually help us help them. Anyway, this should be self explanatory:
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;
Upvotes: 3