当前位置:首页 > 问答 > 正文

SQL去重|数据清洗 SQL Server实现高效数据去重方法及sqlserver中常用去重技巧

SQL去重大作战:SQL Server数据清洗的实用技巧 💻✨

场景引入
刚接手同事的数据库,发现客户表里有500条重复记录?报表数据因为重复项算错总量?别慌!今天带你用SQL Server花式去重,像用吸尘器清理数据灰尘一样简单!🚀


基础去重三板斧 🪓

DISTINCT 简单粗暴法

-- 单列去重(适合临时查询)
SELECT DISTINCT customer_name FROM orders;
-- 多列联合去重
SELECT DISTINCT customer_name, order_date, product_id 
FROM orders;

⚠️ 注意:DISTINCT会扫描整表,百万级数据慎用!

GROUP BY 分组碾压法

-- 获取唯一组合并保留其他列(需聚合函数)
SELECT 
    customer_id, 
    MAX(order_date) AS last_order_date,
    COUNT(*) AS duplicate_count
FROM orders
GROUP BY customer_id;

💡 技巧:配合HAVING COUNT(*) > 1可专门揪出重复数据

ROW_NUMBER() 精准狙击法

-- 给每行打标记后筛选(最灵活)
WITH CTE AS (
    SELECT *,
        ROW_NUMBER() OVER(
            PARTITION BY customer_phone  -- 按手机号分组
            ORDER BY create_time DESC   -- 保留最新记录
        ) AS rn
    FROM customers
)
DELETE FROM CTE WHERE rn > 1;  -- 删除重复项

🎯 适用场景:需要保留特定版本记录(如最新/最早数据)

SQL去重|数据清洗 SQL Server实现高效数据去重方法及sqlserver中常用去重技巧


高级去重黑科技 🔥

临时表交换术(超大数据量适用)

-- 步骤1:创建去重后的临时表
SELECT DISTINCT * INTO #clean_data 
FROM messy_data;
-- 步骤2:清空原表
TRUNCATE TABLE messy_data;
-- 步骤3:插回清洗后数据
INSERT INTO messy_data 
SELECT * FROM #clean_data;
-- 步骤4:清理现场
DROP TABLE #clean_data;

💽 优势:比直接删改原表更安全,避免锁表风险

窗口函数组合拳

-- 同时标记多种重复类型
SELECT 
    product_id,
    RANK() OVER(PARTITION BY category ORDER BY price) AS price_rank,
    DENSE_RANK() OVER(PARTITION BY supplier_id ORDER BY stock) AS stock_rank,
    CASE WHEN COUNT(*) OVER(PARTITION BY barcode) > 1 
         THEN '条码重复' ELSE '正常' END AS dup_status
FROM products;

唯一索引防御术

-- 预防胜于治疗!添加唯一约束
ALTER TABLE employees 
ADD CONSTRAINT UQ_employee_email UNIQUE (email);
-- 尝试插入重复数据时会报错:
-- 违反 UNIQUE KEY 约束 "UQ_employee_email"

🛡️ 最佳实践:重要业务字段建议提前设置约束


实战避坑指南 �

  1. NULL值陷阱

    -- NULL不会被DISTINCT视为相同值!
    SELECT DISTINCT email FROM users; 
    -- 可能返回多条NULL记录
  2. 性能优化TIP

    SQL去重|数据清洗 SQL Server实现高效数据去重方法及sqlserver中常用去重技巧

    • 大数据表先WHERE缩小范围再去重
    • 频繁去重字段考虑创建索引
  3. 特殊去重场景

    -- 只去重连续重复(如日志表中的重复错误)
    WITH numbered_logs AS (
        SELECT *, 
            LAG(error_message) OVER(ORDER BY log_time) AS prev_msg
        FROM error_logs
    )
    SELECT * FROM numbered_logs 
    WHERE error_message <> prev_msg OR prev_msg IS NULL;

总结工具箱 🧰

方法 适用场景 执行效率
DISTINCT 快速查看唯一值
GROUP BY 需要聚合统计时
ROW_NUMBER() 精确控制保留哪条重复记录
临时表法 超大数据量彻底去重

下次遇到数据重复,记得掏出这些神技!像整理凌乱的衣柜一样,让你的数据表清爽如新~ 👔➡️👚👖

(注:本文示例基于SQL Server 2022版本,部分语法可能需要调整以适应其他版本)

发表评论