如何用单条SQL语句在SQL Server中筛选非精确重复并保留长文本
当然可以用单条SELECT语句搞定这个需求!不过具体写法会根据你用的SQL数据库(比如MySQL、PostgreSQL、SQL Server)略有区别,我给你讲核心思路和几种实用的实现方式。
核心逻辑
我们要完成两个目标:
- 剔除所有精确重复的条目
- 在近似重复的组里,只保留最长的文本版本(短文本作为长文本的变体被过滤)
通用兼容性写法(适用于绝大多数数据库)
这个写法用DISTINCT处理精确重复,用NOT EXISTS过滤掉被更长文本包含的短变体,兼容性拉满:
SELECT DISTINCT content FROM text_records tr1 WHERE NOT EXISTS ( SELECT 1 FROM text_records tr2 WHERE tr2.content LIKE CONCAT('%', tr1.content, '%') AND LENGTH(tr2.content) > LENGTH(tr1.content) );
逻辑解释:
DISTINCT直接帮我们干掉所有完全重复的内容,确保每条文本只出现一次NOT EXISTS是核心判断:检查当前文本是否被另一条更长的文本完全包含。如果存在这样的长文本,说明当前文本是短变体,直接过滤;如果不存在,说明它要么是无重复的独立条目,要么就是近似组里最长的那个,保留下来。
注意事项:
- 针对数千条记录的规模,这个写法性能完全够用;如果数据量再大,可以给
content列加全文索引优化匹配速度 - 这里默认“近似重复”是短文本完全是长文本的子串,如果你的变体是其他情况(比如有少量拼写差异),可能需要调整匹配逻辑,但根据你描述的“短文本为长文本的变体”,这个写法刚好适用
进阶窗口函数写法(支持窗口函数的数据库)
如果你的数据库支持窗口函数(比如PostgreSQL 9.4+、SQL Server 2012+),可以用分组标记的方式实现,逻辑更清晰:
SELECT content FROM ( SELECT content, -- 给每个近似重复组标记组内最长文本的长度 MAX(LENGTH(content)) OVER ( PARTITION BY ( -- 把互相包含的文本归为同一组 SELECT MIN(content) FROM text_records tr2 WHERE tr1.content LIKE CONCAT('%', tr2.content, '%') OR tr2.content LIKE CONCAT('%', tr1.content, '%') ) ) AS group_max_length FROM text_records tr1 ) AS subquery -- 只保留组内长度等于最长长度的文本,再去重 WHERE LENGTH(content) = group_max_length GROUP BY content;
这个方法先把所有近似重复的文本归为一组,再在组内筛选出最长的文本,最后通过GROUP BY处理精确重复,适合需要更精细化分组的场景。
内容的提问来源于stack exchange,提问作者gython
相关产品推荐
相关产品推荐

