简体   繁体   中英

Update multiple rows with values of from a specific row based on same ID

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?

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM