You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL Server 2019中能否删除不同列构成重复的行(id3、id4)

当然可以删除id3和id4啦,不过得先明确你的重复判定逻辑——看起来是同一个name下,三个address字段的非空值集合完全一致(比如Jenny的id1是A、B,id3是B、A,顺序不同但内容一样;John的id2是C,id4是C,只是位置不同)。下面给你两种适配SQL Server 2019的靠谱实现方式:

方法1:通过排序拼接地址字段判定重复

这个思路是把每个name下的非空address字段按统一顺序排序后拼接成字符串,这样顺序不同但内容相同的组合就会被判定为重复,然后我们保留每个重复组里id最小的那条,删除其他的。

WITH CTE_Duplicates AS (
    SELECT 
        id,
        name,
        -- 把非空地址排序后拼接成唯一标识字符串
        STRING_AGG(addr, ',') WITHIN GROUP (ORDER BY addr) AS combined_address
    FROM (
        SELECT 
            id,
            name,
            value AS addr
        FROM Table1
        -- 把三个address列转成行,方便统一处理
        UNPIVOT (
            value FOR addr_col IN (address1, address2, address3)
        ) AS unpvt
        WHERE value IS NOT NULL -- 过滤空值,只考虑有效地址
    ) AS addr_rows
    GROUP BY id, name
),
CTE_Rank AS (
    SELECT 
        t.id,
        -- 给每个重复组的记录编号,最小id排第1
        ROW_NUMBER() OVER (PARTITION BY cd.name, cd.combined_address ORDER BY t.id) AS rn
    FROM Table1 t
    JOIN CTE_Duplicates cd ON t.id = cd.id
)
-- 删除编号大于1的记录(也就是重复组里除了最小id之外的记录)
DELETE FROM CTE_Rank WHERE rn > 1;

方法2:通过哈希值匹配地址集合(更可靠)

如果你的地址里可能包含逗号这类会干扰拼接的字符,用哈希值来判定重复会更稳妥。我们还是先处理非空地址,然后生成排序后地址集合的哈希值,再匹配重复组:

WITH CTE_AddressSets AS (
    SELECT 
        id,
        name,
        COUNT(value) AS addr_count, -- 统计非空地址的数量,作为额外校验
        -- 生成排序后地址集合的哈希值
        HASHBYTES('SHA2_256', STRING_AGG(value, ',') WITHIN GROUP (ORDER BY value)) AS addr_hash
    FROM Table1
    UNPIVOT (
        value FOR addr_col IN (address1, address2, address3)
    ) AS unpvt
    WHERE value IS NOT NULL
    GROUP BY id, name
)
DELETE t
FROM Table1 t
JOIN (
    SELECT 
        name,
        addr_hash,
        addr_count,
        MIN(id) AS keep_id -- 每个重复组保留最小的id
    FROM CTE_AddressSets
    GROUP BY name, addr_hash, addr_count
    HAVING COUNT(id) > 1 -- 只处理存在重复的组
) AS dup_groups ON t.name = dup_groups.name 
    -- 匹配当前记录的地址哈希值和数量
    AND HASHBYTES('SHA2_256', STRING_AGG(value, ',') WITHIN GROUP (ORDER BY value)) = dup_groups.addr_hash
    AND COUNT(value) OVER (PARTITION BY t.id) = dup_groups.addr_count
WHERE t.id != dup_groups.keep_id; -- 删除非保留id的记录

重要提醒

执行删除操作前一定要先把DELETE替换成SELECT语句,检查返回的记录是不是你想要删除的id3和id4!比如把第一个方法的最后一行改成SELECT * FROM CTE_Rank WHERE rn > 1;,确认无误后再执行删除,避免误删数据。

内容的提问来源于stack exchange,提问作者user618520

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 00:57:30