将 SELECT DISTINCT 更改为 UPDATE DISTINCT

onm*_*way 4 sql-server update distinct

如何将SELECT DISTINCT查询修改为UPDATE DISTINCT查询?

重要的是它只更新不同的记录,因为有多个记录与每个 [Finance_Project_Number] 相关联(由于 CRUD 操作)。我只想更新一条记录,因为这只会启动验证数据等的不同过程。

如果由于 DISTINCT 导致多条记录折叠为一行,则可以更新其中任何一条记录 - 没关系。

当我运行我的选择查询时,我得到的结果是:6 982:

SELECT DISTINCT
    [Finance_Project_Number]
FROM [InterfaceInfor].[dbo].[ProjectMaster]
WHERE 
    NOT EXISTS 
    (
        SELECT *
        FROM [IMS].[dbo].[THEOPTION]  
        WHERE 
            [InterfaceInfor].[dbo].[ProjectMaster].[Finance_Project_Number] =
            [IMS].[dbo].[THEOPTION].[NAME]
    );
Run Code Online (Sandbox Code Playgroud)

这是我将查询转换为查询的尝试DISTINCT UPDATE,但这会更新 15 353 条记录:

UPDATE [InterfaceInfor].[dbo].[ProjectMaster]
SET 
    [Processing_Result_Text] = 'UNIQUE',
    [Processing_Result] = 0
WHERE 
    NOT EXISTS 
    (
        SELECT *
        FROM [IMS].[dbo].[THEOPTION]  
        WHERE 
            [InterfaceInfor].[dbo].[ProjectMaster].[Finance_Project_Number] =
            [IMS].[dbo].[THEOPTION].[NAME]
    );
Run Code Online (Sandbox Code Playgroud)

Mar*_*ith 9

要从您可以使用的每个不同组中更新任意一个

WITH T
     AS (SELECT ROW_NUMBER() OVER (PARTITION BY [Finance_Project_Number] 
                                       ORDER BY (SELECT 0)) AS RN,
                [Processing_Result_Text],
                [Processing_Result]
         FROM   [InterfaceInfor].[dbo].[ProjectMaster]
         WHERE  NOT EXISTS (SELECT *
                            FROM   [IMS].[dbo].[THEOPTION]
                            WHERE  [InterfaceInfor].[dbo].[ProjectMaster].[Finance_Project_Number] = [IMS].[dbo].[THEOPTION].[NAME]))
UPDATE T
SET    [Processing_Result_Text] = 'UNIQUE',
       [Processing_Result] = 0
WHERE  RN = 1; 
Run Code Online (Sandbox Code Playgroud)

如果您决定有一些标准来选择要更新的行,毕竟只ORDER BY (SELECT 0)需要相应地更改相应的内容,以便首先对所需的目标行进行排序 - 例如,ORDER BY DateInserted desc如果有这样的列,则会按照名为 DateInserted 的列的顺序更新最新的行存在。


这使用公用表表达式(CTE),因为不允许ROW_NUMBER直接在WHERE子句中引用排名函数。允许在与可更新视图相同的情况下通过公共表表达式更新数据(基本上,被更新的数据必须能够直接映射回单个基表中的特定项目)。

如果您还不熟悉排名函数,您可能会SELECT首先发现CTE 中的 -ing 是有益的。

CREATE TABLE #TheOption(NAME VARCHAR(50));

CREATE TABLE #ProjectMaster
(
Finance_Project_Number VARCHAR(10) NOT NULL,
Processing_Result_Text VARCHAR(50) NULL,
Processing_Result INT NULL
);

INSERT INTO #ProjectMaster (Finance_Project_Number, Processing_Result_Text)
VALUES ('A00001', 'A'), 
       ('A00001', 'B'), 
       ('A00001', 'C'), 
       ('B99999', 'D'), 
       ('B99999', 'E'), 
       ('C47474', 'F'), 
       ('C47474', 'G');

INSERT INTO #TheOption (NAME) VALUES('C47474');


WITH T
     AS (SELECT ROW_NUMBER() OVER (PARTITION BY Finance_Project_Number 
                                       ORDER BY (SELECT 0)) AS RN,
                Finance_Project_Number,
                Processing_Result_Text,
                Processing_Result
         FROM   #ProjectMaster pm
         WHERE  NOT EXISTS (SELECT *
                            FROM   #TheOption opt
                            WHERE  pm.Finance_Project_Number =opt.NAME))
SELECT *
FROM T
ORDER BY Finance_Project_Number, RN; 
Run Code Online (Sandbox Code Playgroud)

示例结果如下

在此处输入图片说明

C47474行被滤除,因为它们中的其他表确实存在,以便不符合NOT EXISTS,剩余的行由分组Finance_Project_Number,并且每个组内的分配的序列号。

在这种情况下,黄色行将满足RN = 1条件并进行更新。但是,除非您ORDER BY在保证唯一的表达式上使用子句,否则无法保证在每个组中确切地分配这些数字。如果没有这个,它甚至可能在同一语句的连续执行之间发生变化。