如何在 MySQL 的单个列中删除重复的逗号分隔值

Posted

技术标签:

【中文标题】如何在 MySQL 的单个列中删除重复的逗号分隔值【英文标题】:How to remove duplicate comma separated value in a single column in MySQL 【发布时间】:2013-10-24 12:24:01 【问题描述】:

SELECT id, country FROM my_records

我从 mysql 查询中得到了上述结果,我想从结果中删除重复的 ID。 不是借助 php 代码,而是借助 MySQL 查询。是否有任何功能或查询可以做同样的事情。

谢谢

【问题讨论】:

国家是一栏吧?而不是 GROUP_CONCAT 的结果? 是的 Country 是一列,也不是来自 GROUP_CONCAT 您能提供查询吗?也许它可以帮助我们理解。 @JERRY-thechuha 为您提供查询,我只是在编辑我的问题,这是一个非常简单的查询。 我不认为 MySQL 可以有效地为您做到这一点。它的字符串处理能力缺乏良好的模式提取。您是否需要 MySQL 查询,因为您想删除值(通过 UPDATE),或者您希望在每个查询中删除此解决方案逻辑?如果您正在考虑后者,我相信任何 MySQL 解决方案的性能都会非常差——以至于您可能会重新考虑 MySQL 的要求 【参考方案1】:

我陷入了类似的情况,发现MySql没有提供任何预定义的函数来解决这个问题。

为了克服我创建了一个 UDF,请看下面的定义和用法。

DROP FUNCTION IF EXISTS `get_unique_items`;
DELIMITER //
CREATE FUNCTION `get_unique_items`(str varchar(1000)) RETURNS varchar(1000) CHARSET utf8
BEGIN

        SET @String      = str;
        SET @Occurrences = LENGTH(@String) - LENGTH(REPLACE(@String, ',', ''));
        SET @ret='';
        myloop: WHILE (@Occurrences > 0)
        DO 
            SET @myValue = SUBSTRING_INDEX(@String, ',', 1);
            IF (TRIM(@myValue) != '') THEN
                IF((LENGTH(@ret) - LENGTH(REPLACE(@ret, @myValue, '')))=0) THEN
                        SELECT CONCAT(@ret,@myValue,',') INTO @ret;
                END if;
            END IF;
            SET @Occurrences = LENGTH(@String) - LENGTH(REPLACE(@String, ',', ''));
            IF (@occurrences = 0) THEN 
                LEAVE myloop; 
            END IF;
            SET @String = SUBSTRING(@String,LENGTH(SUBSTRING_INDEX(@String, ',', 1))+2);
        END WHILE;    
SET @ret=concat(substring(@ret,1,length(@ret)-1), '');
return @ret;

END //
DELIMITER ;

示例用法:

SELECT get_unique_items('2,2,2,22,2,3,3,3,34,34,,54,5,45,,65,6,5,,67,6,,34,34,2,3,23,2,32,,3,2,,323') AS 'Items';

结果:

2,22,3,34,54,45,65,67,23,32,323

希望对您有所帮助!

【讨论】:

如果只有一个值没有逗号就不行 @pee2pee 我解决了这个问题。【参考方案2】:

这可能会对你有所帮助。

DELIMITER //

DROP FUNCTION IF EXISTS `find_duplicate_using_comma` //
CREATE FUNCTION `find_duplicate_using_comma` (in_str LONGTEXT) RETURNS LONGTEXT
DETERMINISTIC
NO SQL
BEGIN


DECLARE out_str LONGTEXT DEFAULT NULL; -- pending output
DECLARE next_str TEXT DEFAULT NULL;    -- next element under consideration

dedup:
LOOP

  IF CHAR_LENGTH(TRIM(in_str)) = 0 OR in_str IS NULL THEN
    LEAVE dedup; -- no more data to consider
  END IF;

  SET next_str = SUBSTRING_INDEX(in_str,',',1);                   -- find the next element
  SET in_str = SUBSTRING(in_str FROM (CHAR_LENGTH(next_str) + 1 + 1)); -- remove that element

  SET in_str = TRIM(in_str), next_str = TRIM(next_str); -- trim the new and the rest

  IF FIND_IN_SET(next_str,out_str) OR CHAR_LENGTH(next_str) = 0 THEN -- if empty or already found
    ITERATE dedup;
  END IF;

  SET out_str = CONCAT_WS(',',out_str,next_str); -- append the new to pending output 

END LOOP;

RETURN out_str;

END //

DELIMITER ;

例子:

SELECT find_duplicate_using_comma('6675,8661,8661,8661,8661,8661,8661,8661,8661,8661,8661,8661,8661,8661,8661,8661,8661,8661') AS data;

Result : 6675,8661

【讨论】:

【参考方案3】:

给出的其他解决方案不区分大小写,如果您希望结果区分大小写并且不删除重音匹配(如“o”和“ö”),并寻找精确和严格匹配,这里是代码

如果 utf8mb4_bin 不起作用,请尝试 utf8_bin 或其他二进制类型。

DELIMITER //

DROP FUNCTION IF EXISTS `find_duplicate_using_comma` //
CREATE FUNCTION `find_duplicate_using_comma` (in_str LONGTEXT) RETURNS LONGTEXT
DETERMINISTIC
NO SQL
BEGIN


DECLARE out_str LONGTEXT DEFAULT NULL; -- pending output
DECLARE next_str TEXT DEFAULT NULL;    -- next element under consideration

dedup:
LOOP

  IF CHAR_LENGTH(TRIM(in_str)) = 0 OR in_str IS NULL THEN
    LEAVE dedup; -- no more data to consider
  END IF;

  SET next_str = SUBSTRING_INDEX(in_str,',',1);                   -- find the next element
  SET in_str = SUBSTRING(in_str FROM (CHAR_LENGTH(next_str) + 1 + 1)); -- remove that element

  SET in_str = TRIM(in_str), next_str = TRIM(next_str); -- trim the new and the rest

  IF FIND_IN_SET(next_str collate utf8mb4_bin,out_str collate utf8mb4_bin) OR CHAR_LENGTH(next_str) = 0 THEN -- if empty or already found
    ITERATE dedup;
  END IF;

  SET out_str = CONCAT_WS(',',out_str,next_str); -- append the new to pending output 

END LOOP;

RETURN out_str;

END //

DELIMITER ;

【讨论】:

以上是关于如何在 MySQL 的单个列中删除重复的逗号分隔值的主要内容,如果未能解决你的问题,请参考以下文章

TSQL 将列中的逗号分隔值与逗号分隔参数进行比较

SQL查询以从逗号分隔的列中检索值[重复]

从 Pandas Dataframe Column 中删除重复的逗号,换句话说,我只需要列中的文本,用逗号分隔它们

MySQL函数替换列中的逗号分隔值

R:如何计算列中用逗号分隔的所有字符值?

MySQL查询从字段中删除重复值[重复]