使用 SQL 中的第二高数字更新列



Code:

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中的第二高数字

但是我的代码正在进入其他地方,因为我认为我已经处理了 3 种可能的情况。

我做错了什么?

试试这个:

;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

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

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

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

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 语句更容易和优雅得多

最新更新