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