使用 where 和 order by 子句从 1 更新序列号的列

Posted

技术标签:

【中文标题】使用 where 和 order by 子句从 1 更新序列号的列【英文标题】:Update a column with sequence number from 1 with a where and order by clauses 【发布时间】:2019-05-20 06:39:51 【问题描述】:

我正在尝试执行以下 SQL 查询来更新名为 seq 的列,其中包含特定 ID 的编号序列,但它会引发错误:

关键字“ORDER”附近的语法不正确。

DECLARE @id INT 
SET @id = 0 

UPDATE T_TRNHIST 
SET @id = seq = @id + 1 
WHERE Acc='12344'
OPTION ( MAXDOP 1 )
ORDER BY Recid, trnDate

我哪里出错了?

【问题讨论】:

为什么不用buseROW_NUMBER 代替? 我认为您不能在 UPDATE 语句中使用 ORDER BY。 ***.com/questions/3439110/… 你能告诉我们,这样的查询背后的目的是什么? 【参考方案1】:

您不能在更新语句中使用order by,并且在使用古怪的更新时应该非常小心,因为它们非常不可预测。

一个简单、可靠的解决方案是使用带有row_number 的可更新公用表表达式:

WITH CTE AS
(
    SELECT  seq,
            ROW_NUMBER() OVER(ORDER BY Recid, trnDate) As rn
    FROM T_TRNHIST
)

UPDATE CTE 
SET seq = rn

【讨论】:

【参考方案2】:

您可以尝试UPDATE ... FROM ... 语法,它允许使用JOIN。这是代码 sn-p 以及测试数据:

declare @tbl table (seq int, Acc varchar(10), RecId int, trnDate date);
insert into @tbl values
(null, '12344', 2, '2019-05-05'),
(null, '12344', 1, '2019-05-06'),
(null, '12344', 5, '2019-05-04'),
(null, '12344', 5, '2019-05-03'),
(null, '12355', 1, '2019-05-05');

select * from @tbl

update t1 set t1.seq = t2.rn
from @tbl t1 join (
    select row_number() over (order by RecId, trnDate) rn,
           trnDate,
           RecId,
           Acc
    from @tbl
    where Acc = '12344'
) t2 on t1.trnDate = t2.trnDate and t1.RecId = t2.RecId and t1.Acc = t2.Acc

select * from @tbl

【讨论】:

以上是关于使用 where 和 order by 子句从 1 更新序列号的列的主要内容,如果未能解决你的问题,请参考以下文章

SQL语句中,为啥where子句不能使用列别名,而order by却可以?

sql里 where和order by一起使用是怎样的顺序

在 where 子句和 order by 子句之间的 MySQL 索引

第二章:oracle_sql语句之限制(where子句)和排列数据(order by子句)

为 where 子句和 order_by 创建 MYSQL 索引

oracle用WHERE替代ORDER BY