如何使用 SQL 更新语句为每个 TAG 记录值递增一个值

How do I increment a value using an SQL update statement for each TAG record value

我正在执行一个 SSIS ETL 过程,该过程将数据加载到 table 并使用执行 SQL 语句作为执行的最后一个组件,以根据内容列的值更新 TAG 值.一个例子是

update [payments].[MTFileValidationData_UAT]
set TAG = 'Header'
where left(content,3) = '{1:' and [TransactionId] = ?

这实际上是针对一系列不同的标签完成的。完成此操作后,有一个名为 FileSequenceNumber 的列需要用每个标签的编号进行更新,以便我最终可以将 UAT 和生产文件相互比较以进行测试。

我还需要更新列 FileSequenceNumber 以便为每个文件名的每个标签提供一个序列号。

预期结果:

RowID | TransactionId | FileName | FileType | Tag | Content | Location | FileSequenceNumber |
------+---------------+----------+----------+-----+---------+----------+--------------------+
1        9052312        ABCFile    NULL       Header   XXX     October           1
2        9052312        ABCFile    NULL       Header   ZZZ     October           2
3        9052312        ABCFile    NULL       Header   YYY     October           3
3        9052312        ABCFile    NULL       32B   YYY        October           1
3        9052312        ABCFile    NULL       32B   YYY        October           2
3        9052312        ABCFile    NULL       32B   YYY        October           3       

我相信您希望使用 SQL Server 2012+ 提供的精美 windowing 功能。具体来说,ROW_NUMBER

UPDATE
    T
SET
   FileSequenceNumber = ROW_NUMBER() OVER (PARTITION BY T.Tag ORDER BY RowID)
FROM
    dbo.myTable AS T;

每次标记更改时,partition by 都会重置计数器

order by 指定应如何在标记列中生成序列。

如评论所述,window 函数只能出现在 select 或 oder by 子句中,因此我们必须修改以满足条件。用于工作重现的 DBFiddle https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=d731c14c9e15d70eb3b1d34f7b0f61a8

UPDATE
    T
SET
    T.FileSequenceNumber = TI.FileSequenceNumber
FROM
    dbo.SO_61461648 AS T
    INNER JOIN
    (
    SELECT
        FileSequenceNumber = ROW_NUMBER() OVER (PARTITION BY TI.Tag ORDER BY TI.RowID)
    ,   TI.RowID
    FROM
        dbo.SO_61461648 AS TI
    ) aS TI
    ON TI.RowID = T.RowID;

如果提供的数据是准确的,并且有 4 行具有相同的 RowID,那么您需要采取严厉的方法并转储 table 并重新加载它。

-- Heavy handed approach to dump the table and reload with new value in case RowID is not unique

declare @Intermediary table
(
    RowID int NOT NULL
,   Tag varchar(30) NOT NULL
);
    DELETE T
        OUTPUT DELETED.RowID, DELETED.Tag
        INTO @intermediary(RowID, Tag)
    FROM
        dbo.SO_61461648 AS T;

INSERT INTO
    dbo.SO_61461648
SELECT
    D.*
,    ROW_NUMBER() OVER (PARTITION BY D.Tag ORDER BY D.RowID)
FROM @Intermediary AS D;

SELECT * FROM dbo.SO_61461648 AS T order by RowID, FileSequenceNumber;