使用子查询更新 - 更新超过所需记录

Ju-*_*han 8 sql sql-server

今天是个好日子.我想问一个关于我的SQL语句的问题.我使用的是SQL Server 2008,并且有一个名为Workflow Transaction的表.在这张表中,我有12条记录.下图是表格的内容.

在此输入图像描述

我有这个SQL语句:

UPDATE Workflow_Txn 
SET Status = 1
WHERE [RequestId] IN
(
    SELECT [RequestId]
    FROM Workflow_Txn 
    WHERE [OrderNumber] < (SELECT MAX(OrderNumber) FROM Workflow_Txn WHERE RequestId = 3)      
    AND RequestId = 3
)
Run Code Online (Sandbox Code Playgroud)

我的目标是更新OrderNumber小于最大值的请求ID,它将是WHERE子句中SELECT语句的输出.现在我希望更新的记录只应是所述记录(在代码中,它是RequestId#3).

实际发生的事情是,只有四个记录被更新,它变成五(5)!我现有的SQL语句有问题吗?

Cla*_*edi 6

您的问题是您正在使用RequestId = 3更新所有记录.请考虑您的子查询结果,3以便最终更新所有相关记录.

您的查询等同于do

UPDATE Workflow_Txn 
SET Status = 1
WHERE RequestId = 3
Run Code Online (Sandbox Code Playgroud)

不确定您是否有任何理由让您的查询更加复杂.在我看来,更简单的事情可以解决问题

UPDATE Workflow_Txn 
SET    Status = 1
WHERE  [OrderNumber] < (SELECT MAX(OrderNumber) FROM Workflow_Txn WHERE RequestId = 3)      
       AND RequestId = 3
Run Code Online (Sandbox Code Playgroud)


Gor*_*off 6

您的查询的问题是子查询非常详细,以查找订单号小于最大值的记录.然后它选择具有相同请求的所有内容 - 其中包括最大订单号.

我更喜欢使用CTE修复此问题,如下所示:

with toupdate as (
      select t.*,
             MAX(OrderNumber) as MaxON
      from Workflow_txn
      where RequestId = 3
     )
UPDATE toupdate
    SET Status = 1
    where OrderNumber < MaxON;
Run Code Online (Sandbox Code Playgroud)

我喜欢这种结构,因为我可以单独运行CTE以查看可能更新的记录.

要修复您的查询,您可以将请求更改为使用OrderNumber并重复RequestId = 3:

UPDATE Workflow_Txn 
SET Status = 1
WHERE [RequestId] = 3 and
      OrderNumber in
(
    SELECT [OrderNumber]
    FROM Workflow_Txn 
    WHERE [OrderNumber] < (SELECT MAX(OrderNumber) FROM Workflow_Txn WHERE RequestId = 3)      
    AND RequestId = 3
)
Run Code Online (Sandbox Code Playgroud)