代码:
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种可能的情况。
我做错了什么?
答案 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
陈述更容易和优雅