2020-08-01 00:08:21
SQL 中没有直接内置的字符串去重函数,但可通过拆分、去重、合并的组合操作实现,具体方法因数据库类型和需求场景而异。以下是针对不同场景的详细实现方案:
一、去除字符串中重复的字符(如 'aabbcc' → 'abc')核心逻辑:将字符串拆分为单个字符,去重后重新合并。
PostgreSQL:使用 string_to_array 拆分字符串,unnest 展开为行,DISTINCT 去重,最后用 string_agg 合并。
SELECT string_agg(DISTINCT c, '' ORDER BY c) AS dedupedFROM unnest(string_to_array('aabbcc', NULL)) AS c;结果:'abc'
MySQL 8.0+:需结合递归 CTE 或 JSON 函数模拟拆分过程,代码较复杂,建议优先在应用层处理。
核心逻辑:按分隔符拆分子串,去重后重新拼接。
PostgreSQL:
SELECT string_agg(DISTINCT trim(unnest), ',' ORDER BY trim(unnest))FROM unnest(string_to_array('apple,apple,banana', ','));步骤:
string_to_array 按逗号拆分字符串。
unnest 将数组展开为多行。
trim 去除子串两端空格。
DISTINCT 去重后,string_agg 按逗号重新拼接。
MySQL 8.0+:可通过存储过程或 JSON 函数模拟,但代码冗长,推荐在应用层处理或使用自定义函数(见下文)。
场景:从表中去除重复的字符串记录。方法:直接使用 DISTINCT 或 GROUP BY。
SELECT DISTINCT name FROM users;或
SELECT name FROM users GROUP BY name;四、自定义函数实现通用去重(以 MySQL 为例)需求:处理逗号分隔字符串的去重(如 'apple,apple,banana' → 'apple,banana')。实现步骤:
完整代码:
DELIMITER $$CREATE FUNCTION dedup_string(input TEXT)RETURNS TEXTREADS SQL DATADETERMINISTICBEGIN DECLARE result TEXT DEFAULT ''; DECLARE current_word VARCHAR(255); DECLARE done INT DEFAULT 0; DECLARE cur CURSOR FOR SELECT DISTINCT TRIM(word) FROM ( SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(input, ',', numbers.n), ',', -1) word FROM (SELECT 1 n UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5) numbers WHERE numbers.n <= 1 + (LENGTH(input) - LENGTH(REPLACE(input, ',', ''))) ) t WHERE word != ''; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1; OPEN cur; read_loop: LOOP FETCH cur INTO current_word; IF done THEN LEAVE read_loop; END IF; IF result = '' THEN SET result = current_word; ELSE SET result = CONCAT(result, ',', current_word); END IF; END LOOP; CLOSE cur; RETURN result;END$$DELIMITER ;调用示例:
SELECT dedup_string('apple,apple,banana'); -- 返回 'apple,banana'五、不同数据库的适用性总结简单场景优先使用数据库内置函数组合。
复杂逻辑(如自定义分隔符、多级去重)建议在应用层处理。
核心思路:无论何种场景,字符串去重的本质均为 拆分 → 去重 → 合并,根据数据库特性选择合适工具即可。