Reputation: 15
I want to optimize my query to use CTE and some windows functions for better improvement. I am updating existing rows with specified data from other row but they have the same ID number. The code is for MS SQL.
LinkTable:
ID | TYPE | value1 | Value2 | Value3
-----------------------------------------------
234 | MAT | a | b | c
234 | PMS | null | null | null
234 | AMN | null | null | null
45 | MAT | x | m | n
45 | LKM | null | null | null
45 | DFG | null | null | null
3 | MAT | k | s | q
3 | LKM | null | null | null
The result should be:
ID | TYPE | value1 | Value2 | Value3
-----------------------------------------------
234 | MAT | a | b | c
234 | PMS | a | b | c
234 | AMN | a | b | c
45 | MAT | x | m | n
45 | LKM | x | m | n
45 | DFG | x | m | n
3 | MAT | k | s | q
3 | LKM | k | s | q
I used this code:
UPDATE m
SET m.[value1] = l.[value1]
, m.[value2] = l.[value2]
, m.[value2] = l.[value3]
FROM #LinkTable m
INNER JOIN #LinkTable l on l.[ID] = m.[ID]
WHERE l.[type] = 'MAT'
It updates also the main row from which i take the values.
Could anyone help?
Upvotes: 0
Views: 728
Reputation: 71579
You can use window functions like this:
UPDATE m
SET m.[value1] = m.MATvalue1
, m.[value2] = m.MATvalue2
, m.[value3] = m.MATvalue3
FROM (
SELECT *,
MATvalue1 = MIN(CASE WHEN m.[type] = 'MAT' THEN l.value1 END) OVER (PARTITION BY m.ID),
MATvalue2 = MIN(CASE WHEN m.[type] = 'MAT' THEN l.value2 END) OVER (PARTITION BY m.ID),
MATvalue3 = MIN(CASE WHEN m.[type] = 'MAT' THEN l.value3 END) OVER (PARTITION BY m.ID)
FROM #LinkTable m
) m
WHERE m.[type] <> 'MAT';
Note that this may not necessarily be more performant than Gordon's answer
Upvotes: 1
Reputation: 1269823
Your code is basically fine, but I would add some filters:
UPDATE m
SET m.[value1] = l.[value1],
m.[value2] = l.[value2],
m.[value3] = l.[value3]
FROM #LinkTable m JOIN
#LinkTable l
ON l.[ID] = m.[ID]
WHERE l.[type] = 'MAT' AND
m.type <> 'MAT';
Note: You also have an error in the SET
clause. The column value2
is set twice.
Upvotes: 1