首页 > 解决方案 > 更新表但跳过某些具有特定条件的行

问题描述

我有一个名为的表body_scan,如下所示:

body_no  tag
--------------------
1        noscan
2        noscan
3        missing
4        noscan
5        missing

我还有一个列表,我可以像这样加载到临时表中

tag_no
------
aaa
bbb
ccc

我需要做的是body_scan用临时表中的标签号更新表。

您会注意到 temp 表中只有 3 个标签,而 body_scan 表中有 5 个标签。我需要使用临时表中的值更新标签值“noscan”,并保留缺失的内容。

临时表中标签的顺序与表中的顺序body_no相同body_scan

所以是的,我确实考虑了这个row_number()功能。但我只是不是 100% 确定如何正确定义连接..

请问我该如何实现?

期望的结果是:

body_no  tag
-------------------
1        aaa
2        bbb
3        missing
4        ccc
5        missing

标签: sql-serverjoinsql-server-2012

解决方案


首先,您需要通过向其中添加一个字段来保留数据的输入文件顺序(请注意,一些 ETL 工具会并行插入数据,这会使事情变得混乱,因此您甚至可能需要将此列添加到文件中)identitytemp_table

完成后,您需要在 body_scan 中生成一个可以加入的密钥。这只是ROW_NUMBER()在现有表上,不包括丢失的行

这将返回该行以及它应该匹配的内容temp_table

SELECT 
body_no,
ROW_NUMBER() OVER (ORDER BY body_no) RN
FROM body_scan
WHERE tag<> 'missing';

这加入了临时表(假设您的序号列称为 RowID)

SELECT T1.body_no, T1.tag, T1.RN, T2.tag_no
FROM
(
SELECT 
body_no,tag,
ROW_NUMBER() OVER (ORDER BY body_no) RN
FROM body_scan
WHERE tag<> 'missing'
) T1
INNER JOIN
temp_table T2 
ON T1.RN=T2.RowID;

这会将其更新回表格:

UPDATE TGT
SET tag=SRC.tag_no
FROM body_scan TGT
INNER JOIN
(
    SELECT T1.body_no, T2.tag_no
    FROM
    (
    SELECT 
    body_no,tag,
    ROW_NUMBER() OVER (ORDER BY body_no) RN
    FROM body_scan
    WHERE tag<> 'missing'
    ) T1
    INNER JOIN
    temp_table T2 
    ON T1.RN=T2.RowID 
) SRC
ON SRC.body_no=TGT.body_no;

(有六种方法可以编写最终语句,但我更喜欢这种方式,因为您可以在子选择中看到您正在更新的数据集)


推荐阅读