更新SQL中第二个最高编号的列

时间:2017-01-28 08:15:55

标签: sql sql-server

代码:

update [MemberBackup].[dbo].[uid3times$]
set rc2tobedeleted =
case when rc1 > rc2 and rc1 > rc3 and rc2 < rc3 then rc2
when  rc2 > rc3 and rc2 > rc1  and rc1 < rc3 then rc1
when rc3 > rc1 and rc3 > rc2  and rc1 < rc2 then rc1 
else 0 end 

我有3列rc1,rc2,rc3和3列中的数字是随机的我想更新/设置rc2tobedeleted中的第2个最高数字

但是我的代码即将到来,因为我认为我已经处理了3种可能的情况。

我做错了什么?

2 个答案:

答案 0 :(得分:4)

试试这个:

;WITH ToUpdate AS (
   SELECT rc2tobedeleted, t.v AS val
   FROM [MemberBackup].[dbo].[uid3times$]
   CROSS APPLY (
      SELECT x.v
      FROM (VALUES (rc1), (rc2), (rc3) ) AS x(v)
      ORDER BY x.v DESC 
      OFFSET 1 ROWS
      FETCH NEXT 1 ROWS ONLY) AS t
UPDATE ToUpdate
SET rc2tobedeleted = val

我认为与WHEN表达式的多个CASE子句相比,上述查询具有更清晰易懂的结构。

查询使用VALUES表值构造函数来构建由字段rc1, rc2, rc3的值组成的内联表。使用SQL Server 2012以后的OFFSET FETCH子句,我们可以获得第二高的值。

最后,使用CTE执行UPDATE操作:更新从CTE传播到存储在数据库中的实际表的基础行。

答案 1 :(得分:2)

Giorgos答案很棒,但Sql server 2012及以上

可以这样简化
UPDATE [MemberBackup].[dbo].[uid3times$]
SET    rc2tobedeleted = (SELECT rc
                         FROM   (VALUES (rc1),(rc2),(rc3) ) tc (rc)
                         ORDER  BY rc DESC
                         OFFSET 1 ROWS FETCH next 1 rows only) 

旧版本使用此

UPDATE [MemberBackup].[dbo].[uid3times$]
SET    rc2tobedeleted = (SELECT rc
                         FROM   (SELECT Row_number()OVER(ORDER BY rc DESC) rn,rc
                                 FROM   (VALUES (rc1),(rc2),(rc3) ) tc (rc)) a
                         WHERE  rn = 2) 

这里的想法是,将三列拆分为单列并在不透露的行上生成行号,并更新行号为2的记录

这种方法的另一个优点是,即使你有超过3个三列,你想找到第n个记录,那么它比笨拙的CASE陈述更容易和优雅