Oracle数据库数据编程SQL<01. 课外关注:数据库查重方法全面详解>

news2025/4/16 8:36:43

查重是数据库管理和数据分析中的常见需求,以下是各种查重方法的全面总结,涵盖不同场景和技术手段。

更多Oracle学习内容请查看:Oracle保姆级超详细系列教程_Tyler先森的博客-CSDN博客

目录

一、基础SQL查重方法

1. 使用GROUP BY和HAVING

2. 使用窗口函数

3. 使用自连接

二、高级查重技术

1. 模糊查重(相似度匹配)

1.1 使用SOUNDEX函数(语音相似)

1.2 使用Levenshtein距离(编辑距离)

1.3 使用UTL_MATCH包(Oracle)

2. 大数据量查重优化

2.1 使用HASH值比较

2.2 分区查重

3. 跨表查重

三、数据库特定查重方法

1. Oracle查重技术

1.1 使用分析函数

1.2 使用Oracle GoldenGate或Data Compare工具

2. MySQL查重技术

2.1 使用临时表删除重复

2.2 使用INSERT IGNORE

3. SQL Server查重技术

3.1 使用MERGE语句

3.2 使用SSIS数据流任务

四、程序化查重方法

1. Python + Pandas

2. Java查重示例

3. 使用Apache Spark(大数据场景)

五、数据质量工具集成

1. 专业数据质量工具

2. 开源工具

六、查重后的处理策略

1. 删除重复数据

2. 合并重复记录

3. 标记重复记录

七、预防重复数据的策略

1. 数据库约束

2. 使用序列/自增ID

3. 应用层校验

4. 使用MERGE/UPSERT

八、特殊数据类型查重

1. JSON数据查重

2. 时空数据查重

3. 图像/二进制数据查重

九、性能优化建议

十、行业特定查重案例

1. 金融行业(反洗钱)

2. 电商行业(刷单检测)

3. 医疗行业(重复就诊)


一、基础SQL查重方法

1. 使用GROUP BYHAVING

-- 单列查重
SELECT column_name, COUNT(*)
FROM table_name
GROUP BY column_name
HAVING COUNT(*) > 1;

-- 多列组合查重
SELECT column1, column2, COUNT(*)
FROM table_name
GROUP BY column1, column2
HAVING COUNT(*) > 1;

2. 使用窗口函数

-- 使用ROW_NUMBER()标记重复行
SELECT *,
       ROW_NUMBER() OVER(PARTITION BY column1, column2 ORDER BY id) AS rn
FROM table_name;

-- 提取重复记录
WITH dup_check AS (
    SELECT *,
           ROW_NUMBER() OVER(PARTITION BY column1, column2 ORDER BY id) AS rn
    FROM table_name
)
SELECT * FROM dup_check WHERE rn > 1;

3. 使用自连接

-- 查找完全重复的行
SELECT a.*
FROM table_name a
JOIN table_name b 
ON a.column1 = b.column1 
AND a.column2 = b.column2
AND a.id <> b.id;  -- 排除自连接

二、高级查重技术

1. 模糊查重(相似度匹配)

1.1 使用SOUNDEX函数(语音相似)

SELECT a.name, b.name
FROM customers a, customers b
WHERE a.id < b.id  -- 避免重复比较
AND SOUNDEX(a.name) = SOUNDEX(b.name);

1.2 使用Levenshtein距离(编辑距离)

-- Oracle需要自定义函数
CREATE OR REPLACE FUNCTION levenshtein( s1 IN VARCHAR2, s2 IN VARCHAR2 )
RETURN NUMBER IS [...];

SELECT a.name, b.name
FROM products a, products b
WHERE a.id < b.id
AND levenshtein(a.name, b.name) <= 3;  -- 允许3个字符差异

1.3 使用UTL_MATCH包(Oracle)

SELECT a.name, b.name, 
       UTL_MATCH.JARO_WINKLER_SIMILARITY(a.name, b.name) AS similarity
FROM customers a, customers b
WHERE a.id < b.id
AND UTL_MATCH.JARO_WINKLER_SIMILARITY(a.name, b.name) > 90;  -- 相似度>90%

2. 大数据量查重优化

2.1 使用HASH值比较

-- 创建哈希列
ALTER TABLE large_table ADD hash_value RAW(16);

-- 更新哈希值(组合关键列)
UPDATE large_table 
SET hash_value = DBMS_CRYPTO.HASH(
    UTL_I18N.STRING_TO_RAW(column1||column2||column3, 'AL32UTF8'),
    2);  -- 2=MD4算法

-- 查找重复哈希
SELECT hash_value, COUNT(*)
FROM large_table
GROUP BY hash_value
HAVING COUNT(*) > 1;

2.2 分区查重

-- 按日期分区查重
SELECT user_id, action_date, COUNT(*)
FROM user_actions
PARTITION (p_2023_01)  -- 指定分区
GROUP BY user_id, action_date
HAVING COUNT(*) > 1;

3. 跨表查重

-- 查找两个表中都存在的记录
SELECT a.*
FROM table1 a
WHERE EXISTS (
    SELECT 1 FROM table2 b
    WHERE a.key_column = b.key_column
);

-- 使用INTERSECT
SELECT key_column FROM table1
INTERSECT
SELECT key_column FROM table2;

三、数据库特定查重方法

1. Oracle查重技术

1.1 使用分析函数

-- 查找重复并保留最新记录
SELECT *
FROM (
    SELECT t.*,
           ROW_NUMBER() OVER(PARTITION BY id_number, name ORDER BY create_date DESC) AS rn
    FROM persons
) 
WHERE rn = 1;  -- 只保留每组最新记录

1.2 使用Oracle GoldenGate或Data Compare工具

专业工具提供可视化比较和同步功能。

2. MySQL查重技术

2.1 使用临时表删除重复

-- 创建临时表存储唯一记录
CREATE TABLE temp_table AS
SELECT DISTINCT * FROM original_table;

-- 替换原表
RENAME TABLE original_table TO old_table, temp_table TO original_table;

2.2 使用INSERT IGNORE

-- 跳过重复记录插入
INSERT IGNORE INTO target_table
SELECT * FROM source_table;

3. SQL Server查重技术

3.1 使用MERGE语句

MERGE INTO target_table t
USING source_table s
ON t.key_column = s.key_column
WHEN NOT MATCHED THEN
    INSERT (col1, col2) VALUES (s.col1, s.col2);

3.2 使用SSIS数据流任务

SQL Server Integration Services提供图形化查重组件。

四、程序化查重方法

1. Python + Pandas

import pandas as pd

# 读取数据
df = pd.read_sql("SELECT * FROM table_name", engine)

# 简单查重
duplicates = df[df.duplicated(subset=['col1', 'col2'], keep=False)]

# 模糊查重(使用fuzzywuzzy)
from fuzzywuzzy import fuzz
dupe_pairs = []
for i, row1 in df.iterrows():
    for j, row2 in df.iterrows():
        if i < j and fuzz.ratio(row1['name'], row2['name']) > 85:
            dupe_pairs.append((i, j))

2. Java查重示例

// 使用内存哈希集查重
Set<String> uniqueKeys = new HashSet<>();
List<Record> duplicates = new ArrayList<>();

for (Record record : records) {
    String compositeKey = record.getField1() + "|" + record.getField2();
    if (!uniqueKeys.add(compositeKey)) {
        duplicates.add(record);
    }
}

3. 使用Apache Spark(大数据场景)

val df = spark.read.jdbc(...)  // 从数据库读取

// 精确查重
val duplicates = df.groupBy("col1", "col2")
                  .count()
                  .filter("count > 1")

// 近似查重(使用MinHash)
import org.apache.spark.ml.feature.MinHashLSH
val mh = new MinHashLSH().setInputCol("features").setOutputCol("hashes")
val model = mh.fit(featurizedData)
val dupCandidates = model.approxSimilarityJoin(featurizedData, featurizedData, 0.8)

五、数据质量工具集成

1. 专业数据质量工具

  • Informatica Data Quality
  • IBM InfoSphere QualityStage
  • Talend Data Quality
  • Oracle Enterprise Data Quality

2. 开源工具

  • OpenRefine:强大的数据清洗和查重工具
  • DataCleaner:提供可视化查重规则配置
  • Dedupe.io:基于机器学习的智能去重

六、查重后的处理策略

1. 删除重复数据

-- Oracle使用ROWID删除重复
DELETE FROM table_name
WHERE ROWID NOT IN (
    SELECT MIN(ROWID)
    FROM table_name
    GROUP BY column1, column2
);

-- MySQL使用临时表
CREATE TABLE temp_table AS SELECT DISTINCT * FROM original_table;
TRUNCATE TABLE original_table;
INSERT INTO original_table SELECT * FROM temp_table;
DROP TABLE temp_table;

2. 合并重复记录

-- 合并重复客户记录
UPDATE customers c1
SET (address, phone) = (
    SELECT COALESCE(c1.address, c2.address),
           COALESCE(c1.phone, c2.phone)
    FROM customers c2
    WHERE c1.email = c2.email
    AND c2.ROWID = (
        SELECT MIN(ROWID) 
        FROM customers c3 
        WHERE c3.email = c1.email
    )
)
WHERE c1.ROWID <> (
    SELECT MIN(ROWID) 
    FROM customers c4 
    WHERE c4.email = c1.email
);

3. 标记重复记录

-- 添加重复标记列
ALTER TABLE customers ADD is_duplicate NUMBER(1) DEFAULT 0;

-- 标记重复记录
UPDATE customers c
SET is_duplicate = 1
WHERE EXISTS (
    SELECT 1 FROM customers c2
    WHERE c.email = c2.email
    AND c.ROWID > c2.ROWID
);

七、预防重复数据的策略

1. 数据库约束

-- 唯一约束
ALTER TABLE products ADD CONSTRAINT uk_product_code UNIQUE (product_code);

-- 复合唯一约束
ALTER TABLE orders ADD CONSTRAINT uk_order_item UNIQUE (order_id, product_id);

2. 使用序列/自增ID

-- Oracle序列
CREATE SEQUENCE customer_id_seq START WITH 1 INCREMENT BY 1;

-- MySQL自增
CREATE TABLE customers (
    id INT AUTO_INCREMENT PRIMARY KEY,
    ...
);

3. 应用层校验

// Java示例-插入前检查
public boolean isCustomerExist(String email) {
    String sql = "SELECT 1 FROM customers WHERE email = ?";
    try (Connection conn = dataSource.getConnection();
         PreparedStatement stmt = conn.prepareStatement(sql)) {
        stmt.setString(1, email);
        try (ResultSet rs = stmt.executeQuery()) {
            return rs.next();
        }
    }
}

4. 使用MERGE/UPSERT

-- Oracle MERGE
MERGE INTO customers t
USING (SELECT 'john@example.com' email, 'John' name FROM dual) s
ON (t.email = s.email)
WHEN NOT MATCHED THEN
    INSERT (email, name) VALUES (s.email, s.name)
WHEN MATCHED THEN
    UPDATE SET t.name = s.name;

八、特殊数据类型查重

1. JSON数据查重

-- PostgreSQL JSONB查重
SELECT json_column->>'id', COUNT(*)
FROM json_table
GROUP BY json_column->>'id'
HAVING COUNT(*) > 1;

-- Oracle JSON查重
SELECT JSON_VALUE(json_column, '$.id'), COUNT(*)
FROM json_table
GROUP BY JSON_VALUE(json_column, '$.id')
HAVING COUNT(*) > 1;

2. 时空数据查重

-- 地理位置相近查重(PostGIS)
SELECT a.id, b.id
FROM locations a, locations b
WHERE a.id < b.id
AND ST_DWithin(a.geom, b.geom, 100);  -- 100米范围内视为重复

-- 时间范围重叠查重
SELECT a.event_id, b.event_id
FROM events a, events b
WHERE a.event_id < b.event_id
AND a.end_time > b.start_time
AND a.start_time < b.end_time;

3. 图像/二进制数据查重

-- 使用哈希比较图像
SELECT image_hash, COUNT(*)
FROM images
GROUP BY image_hash
HAVING COUNT(*) > 1;

-- Oracle使用DBMS_CRYPTO
SELECT DBMS_CRYPTO.HASH(image_data, 2) AS img_hash
FROM images;

九、性能优化建议

  1. 索引优化:为查重字段创建合适索引
    CREATE INDEX idx_customer_email ON customers(email);
  2. 分批处理:大数据集分批次查重
    -- 按时间范围分批
    SELECT * FROM orders 
    WHERE order_date BETWEEN TO_DATE('2023-01-01') AND TO_DATE('2023-01-31')
    GROUP BY customer_id, product_id
    HAVING COUNT(*) > 1;
  3. 物化视图:预计算重复数据
    CREATE MATERIALIZED VIEW duplicate_orders_mv
    REFRESH COMPLETE ON DEMAND
    AS SELECT customer_id, product_id, COUNT(*)
       FROM orders
       GROUP BY customer_id, product_id
       HAVING COUNT(*) > 1;
  4. 并行查询
    SELECT /*+ PARALLEL(4) */ column1, COUNT(*)
    FROM large_table
    GROUP BY column1
    HAVING COUNT(*) > 1;
  5. 使用NoSQL解决方案:对于超大规模数据,考虑Redis或MongoDB等方案

十、行业特定查重案例

1. 金融行业(反洗钱)

-- 查找同一天多笔大额交易
SELECT customer_id, transaction_date, COUNT(*), SUM(amount)
FROM transactions
GROUP BY customer_id, transaction_date
HAVING COUNT(*) > 3 AND SUM(amount) > 100000;

2. 电商行业(刷单检测)

-- 检测相同IP短时间内下单
SELECT ip_address, COUNT(DISTINCT user_id), COUNT(*)
FROM orders
WHERE order_time > SYSDATE - 1/24  -- 最近1小时
GROUP BY ip_address
HAVING COUNT(DISTINCT user_id) > 3 OR COUNT(*) > 5;

3. 医疗行业(重复就诊)

-- 查找同一患者相同诊断重复挂号
SELECT patient_id, diagnosis, visit_date, COUNT(*)
FROM medical_records
GROUP BY patient_id, diagnosis, TRUNC(visit_date)
HAVING COUNT(*) > 1;

以上方法涵盖了从基础到高级的各种查重技术,实际应用中应根据数据特点、系统环境和业务需求选择合适的方法组合。对于关键业务系统,建议建立常态化的数据质量检查机制,而不仅仅是临时查重。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2335823.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【大模型实战篇】--阿里云百炼搭建MCP Agent

MCP协议&#xff08;Model Communication Protocol&#xff0c;模型通信协议&#xff09;是大语言模型&#xff08;LLM&#xff09;与外部系统或其他模型交互时的一种标准化通信框架&#xff0c;旨在提升交互效率、安全性和可扩展性。 目录 1.阿里云百炼--MCP 1.1.MCP 服务接…

基于PySide6与pycatia的CATIA智能倒角工具开发全解析

引言&#xff1a;工业设计中的倒角革命 在机械设计领域&#xff0c;倒角操作是零件加工前的必要工序。传统手动操作效率低下且易出错本文基于PySide6pycatia技术栈&#xff0c;提出一种支持批量智能倒角、参数动态校验、跨层级操作的自动化方案&#xff0c;其核心突破体现在&a…

css 二维码始终显示在按钮的正下方,并且根据不同的屏幕分辨率自动调整位置

一、需求 “求职入口” 下面的浮窗位置在其正下方&#xff0c;并且浏览器分辨的改变&#xff08;拖动浏览器&#xff09;&#xff0c;位置依旧在最下方 二、实现 <div class"btn_box"><div class"btn_link id"js-apply">求职入口<di…

串口接收的使用-中断

1、引言 单片机串口、按键等等这种外部输入的&#xff0c; 用轮询的方式非常浪费资源&#xff0c;所以最好的方法就是使用中断接收数据。 2、串口 对于串口中断&#xff0c; 使用的非常频繁。 1. 基本原理 串口中断接收通过以下方式工作&#xff1a; 当串口接收到一个字节…

处理 Flutter 没有反应

现象 有以下几种 VS Code 中 Initializing the Flutter SDK. This may take a few minutes. 会一直维持在这个右下角提示窗, 但是无后续动作 Flutter CMD flutter_console.bat 执行 --version 或者 doctor [-v] 没有任何输出, 命令卡住 解决办法 参考官方说明 管理员身份…

入门51单片机(1)-----点灯大师梦开始的地方

前言 这一次的博客主要是要记录一下学习的记录的,方便以后去复习一下的&#xff0c;当然这篇博客还是针于零基础的伙伴萌&#xff0c;看完这篇博客&#xff0c;大家就可以学会点灯了。 安装软件 方法一下一下来教&#xff01;&#xff01;萌新宝贝萌可以学会的&#xff01;帮…

3.数组(随想录)

1.二分查找 *2.移除元素 还有一个小优化&#xff08;可以不看&#xff09; 3.有序数组的平方 *4.长度最小的子数组 &#xff08;3种解法&#xff09; 5.螺旋矩阵 ||

C#设计模式-状态模式

状态模式案例解析&#xff1a;三态循环灯的实现 案例概述 本案例使用 状态模式&#xff08;State Pattern&#xff09; 实现了一个 三态循环灯 的功能。每点击一次按钮&#xff0c;灯的状态会按顺序切换&#xff08;状态1 → 状态2 → 状态3 → 状态1...&#xff09;&#xff…

字节跳动开源 LangManus:不止是 Manus 平替,更是下一代 AI 自动化引擎

当 “AI 自动化” 成为科技领域最炙手可热的关键词&#xff0c;我们仿佛置身于一场激动人心的变革前夜。各行各业都在翘首以盼&#xff0c;期待 AI 技术能够真正解放生产力&#xff0c;将人类从繁琐重复的工作中解脱出来。在这个充满无限可能的时代&#xff0c;字节跳动悄然发布…

21.C++11

1.列表初始化 1.1C11中的{} •C11以后想统⼀初始化⽅式&#xff0c;试图实现⼀切对象皆可⽤{}初始化&#xff0c;{}初始化也叫做列表初始化。 • 内置类型⽀持&#xff0c;⾃定义类型也⽀持&#xff0c;⾃定义类型本质是类型转换&#xff0c;中间会产⽣临时对象&#xff0c;最…

STM32 HAL库之WDG示例代码

独立看门狗&#xff08;IWDG&#xff09; 初始化独立看门狗&#xff0c;在main.c中的 MX_IWDG_Init();&#xff0c;也就是iwdg.c中的初始化代码 void MX_IWDG_Init(void) {/* USER CODE BEGIN IWDG_Init 0 *//* USER CODE END IWDG_Init 0 *//* USER CODE BEGIN IWDG_Init 1 …

Spring AI 发布了它的 1.0.0 版本的第七个里程碑(M7)

Spring AI 发布了它的 1.0.0 版本的第七个里程碑&#xff08;M7&#xff09;&#xff0c;下个月就是 RC1&#xff0c;紧接着就是 GA&#xff01;&#xff0c;对于我们 Java 开发者来说&#xff0c;这绝对是个值得关注的好消息&#xff01; 但是对于 Java 学习者来说&#xff0c…

jdk 安装

oracle官网 : Java Archive | Oracle 中国 export JAVA_HOME/Users/xxxxx/app/services/x86jdk/jdk1.8.0_431.jdk/Contents/Home export PATH$JAVA_HOME/bin:$PATH 华为镜像网站&#xff1a;Index of java-local/jdk

3.2.2.2 Spring Boot配置视图控制器

在Spring Boot中配置视图控制器可以简化页面跳转跳逻辑。通过实现WebMvcConfigurer接口的addViewControllers方法&#xff0c;可以直接将URL映射到特定的视图&#xff0c;而无需编写控制器类。例如&#xff0c;将根路径"/"映射到welcome.html视图&#xff0c;当访问应…

华为OD机试真题——找出两个整数数组中同时出现的整数(2025A卷:100分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

2025 A卷 100分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式! 华为OD机试真题《找出两个整数数组中同时出现的整数》: 目录 题目名称:找出两个整数数组中同…

烽火ai场控接入deepseek自动回复话术软件

要将烽火AI场控软件与DeepSeek自动回复话术软件进行对接&#xff0c;实现直播间自动互动功能&#xff0c;需通过API接口或脚本工具完成数据互通。以下是具体操作步骤及注意事项&#xff1a; 确认兼容性与准备工作 软件支持检查 确认烽火AI场控是否开放API接口&#xff08;一般需…

【Linux系统】进程地址空间

命令行参数 int main (int argc, char* argv[]) 命令行参数列表 argc&#xff1a;参数的个数argv&#xff1a;参数的清单 int main (int argc, char* argv[]) {printf("argc: %d\n",argc);for(int i 0; i < argc; i){printf("argv[%d] : %s \n", i…

记录学习的第二十六天

还是每日一题。 今天这道题有点难度&#xff0c;我看着题解抄的。 之后做了两道双指针问题。 这道题本来是想用纯暴力做的&#xff0c;结果出错了。&#x1f613;

python成功解决AttributeError: can‘t set attribute ‘lines‘

文章目录 报错信息与原因分析解决方法示例代码代码解释总结 报错信息与原因分析 在使用 matplotlib绘图时&#xff0c;若尝试使用 ax.lines []来清除图表中的线条&#xff0c;会遇到AttributeError: can’t set attribute错误。这是因为 ax.lines是一个只读属性&#xff0c;不…

如何建立可复用的项目管理模板

建立可复用的项目管理模板能够显著提高项目执行效率、减少重复劳动、确保项目管理标准化。在企业中&#xff0c;项目管理往往涉及多个步骤和多个团队&#xff0c;然而每次开始一个新项目时&#xff0c;如果都从头开始设计流程和文档&#xff0c;势必浪费大量的时间和精力。通过…