将具有特定值的列更新为具有相同ID的另一列上具有最大值的值

时间:2015-09-07 14:39:12

标签: sql-server sql-update

已在另一个问题中问过这个问题,但标准发生了变化。

我的表:

 ID | NumDate  | Number
-------------------
| 1 | 20150101 | 0x
| 1 | 20140101 | 12345678
| 1 | 20130101 | 12345
| 2 | 20150101 | 0x
| 2 | 20130101 | 0x
| 2 | 20091111 | 242424
| 3 | 20150101 | 88888
| 3 | 20141010 | 88888
| 4 | 20150101 | 0x
| 4 | 20141010 | 0x
| 5 | 20141010 | 0101010
| 5 | 20141010 | 0101010
| 5 | 20141010 | 0x

每个'0x'必须更新为'Number',最大'NumDate'不是'0x'。

如果不存在除“0x”之外的其他值,则不进行更新。

需要的结果:

ID  | NumDate   | Number
-------------------
| 1 | 20150101 | 12345678      <-- ID = 1, Updated
| 1 | 20140101 | 12345678
| 1 | 20130101 | 12345
| 2 | 20150101 | 242424        <-- ID = 2, Updated
| 2 | 20130101 | 242424        <-- ID = 2, Updated
| 2 | 20091111 | 242424
| 3 | 20150101 | 88888         <- No change on id = 3, '88888' on both rows
| 3 | 20141010 | 88888         <- No change on id = 3, '88888' on both rows
| 4 | 20150101 | 0x            <- No change, there's no *better* 'Number' 
| 4 | 20141010 | 0x            <- No change, there's no *better* 'Number'
| 5 | 20141010 | 0101010
| 5 | 20141010 | 0101010 
| 5 | 20141010 | 0101010       <-- Updated

试过这个(thnx Kaf):

;WITH CTE AS (
    SELECT ID, Number, Max(NumDate) NumDate
    FROM TEST_03
    WHERE Number <> '0X'
    GROUP BY ID
)
UPDATE ut SET Number = c.Number
FROM TEST_03 ut
    JOIN CTE c ON ut.ID = c.ID
WHERE ut.Number = '0X'
    JOIN CTE c ON ut.ID = c.ID
WHERE ut.Number = '0x'

我明白了:

Column 'TEST_03.Number' is invalid in the select list because it is not 
contained in either an aggregate function or the GROUP BY clause.

我确实看到了聚合函数的使用错误。不适合这里?

现在,我不知道如何处理这个问题。 也许我应该将'ID','Numdate'和'Number'复制到另一个表并使用JOIN进行更新,以保持简单?例子,有人吗?

或者也许有办法在现有的表中制作它?

任何帮助将不胜感激, 提前谢谢!

3 个答案:

答案 0 :(得分:1)

尝试在CTE中按编号添加分组并删除最后一个联接 see the demo

;WITH CTE AS (
SELECT ID, Number, Max(NumDate) NumDate
FROM TEST_03
WHERE Number <> '0X'
GROUP BY ID, Number
)
UPDATE ut SET Number = c.Number
FROM TEST_03 ut
    JOIN CTE c ON ut.ID = c.ID
WHERE ut.Number = '0X'

答案 1 :(得分:1)

这样的事情应该有效:

update t3
set Number = t1.Number
from dbo.test t3 join dbo.test t1 on t3.id = t1.id
join
(
select id, max(numDate) as maxdate
from dbo.test
where number<>'0x'
group by id
) t2
on t1.id = t2.id and t1.NumDate = t2.maxdate
where t3.number = '0x'

答案 2 :(得分:0)

我认为最佳解决方案是使用CROSS APPLY:

;WITH CTE AS (
    SELECT t1.Number, t2.Number as NewNumber
    FROM TEST_03 t1
    CROSS APPLY
    (
       SELECT top 1 Number 
       FROM TEST_03
       WHERE
         t1.ID = ID
         and Number <> '0X'
       ORDER BY NumDate DESC
    ) t2
    WHERE t1.Number = '0X'
)
UPDATE CTE
SET Number = NewNumber