合并两列,多行忽略重复 - MySQL

时间:2014-07-30 07:47:57

标签: mysql sql

这可能是一个愚蠢的问题。不适合我:老实说,我对MySql查询并不熟悉,所以我正在寻求一些帮助。

我有一张桌子:

id |      type_a              |    type_b        |
__________________________________________________
 1 | *color_1*color_2*color_3*| *color_1*        |
 2 | *color_3*                | *color_3*color_2*|
 3 | *color_2*color_3*        | *color_4*        |
 4 | *color_1*color_3*color_4*|                  |
 5 | *color_4*                | *color_5*        |
__________________________________________________

我想移动" type_b" " type_a"中的列内容列忽略重复字段(由*和*分隔,例如: color_1 。这种存储由Joomla组件构建)。

我想得到这个最终结果:

    id |      type_a              |  type_b |  
    _________________________________________
     1 | *color_1*color_2*color_3*|         |
     2 | *color_3*color_2*        |         |
     3 | *color_2*color_3*color_4*|         |
     4 | *color_1*color_3*color_4*|         |
     5 | *color_4*color_5*        |         |
    _________________________________________

实现类似目标的最佳方法是什么?

感谢所有人!

1 个答案:

答案 0 :(得分:1)

您可以使用此声明(不,它看起来不太好),假设您的表名为example

UPDATE
    example e1
SET
    e1.type_a = (
        SELECT
            CONCAT('*', GROUP_CONCAT(DISTINCT n1.value ORDER BY n1.value SEPARATOR '*'), '*') as type_a
        FROM ( 
            SELECT
                id, 
            CASE 
                WHEN SUBSTRING_INDEX(SUBSTRING_INDEX(TRIM(BOTH '*' FROM e.type_a), '*', n.n), '*', -1) = '' THEN NULL
                ELSE SUBSTRING_INDEX(SUBSTRING_INDEX(TRIM(BOTH '*' FROM e.type_a), '*', n.n), '*', -1)
            END value
            FROM example e CROSS JOIN (
                SELECT 
                    a.N + b.N * 10 + 1 AS n
                FROM
                    (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
                   ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
                ORDER BY n
            ) n
            WHERE 
                n.n <= 1 + (LENGTH(e.type_a) - LENGTH(REPLACE(e.type_a, '*', '')))
            UNION
            SELECT
                id, 
            CASE 
                WHEN SUBSTRING_INDEX(SUBSTRING_INDEX(TRIM(BOTH '*' FROM e.type_b), '*', n.n), '*', -1) = '' THEN NULL
                ELSE SUBSTRING_INDEX(SUBSTRING_INDEX(TRIM(BOTH '*' FROM e.type_b), '*', n.n), '*', -1)
            END value
            FROM example e CROSS JOIN (
                SELECT 
                    a.N + b.N * 10 + 1 AS n
                FROM
                    (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
                   ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
                ORDER BY n
            ) n
            WHERE 
                n.n <= 1 + (LENGTH(e.type_b) - LENGTH(REPLACE(e.type_b, '*', '')))
        ) n1
        WHERE 
            n1.id = e1.id
        GROUP BY 
            id
    ),
    e1.type_b = ''
;
SELECT语句的

Demo

<强>解释

基本上我调整了methodpeterm来完成拆分。我必须先通过TRIM删除外部*

为了允许空字符串作为列值,我添加了CASE构造,以消除这些值。如果您的列具有NULL值,则可以用

替换CASE
SUBSTRING_INDEX(SUBSTRING_INDEX(TRIM(BOTH '*' FROM e.type_a), '*', n.n), '*', -1)

SUBSTRING_INDEX(SUBSTRING_INDEX(TRIM(BOTH '*' FROM e.type_a), '*', n.n), '*', -1)

此构造的UNION(没有ALL关键字)将为我们提供不同颜色值的列表,并且使用GROUP BY id和GROUP_CONCAT,我们将获得*分隔值列表。最后,我们添加了一个前导*以符合您的要求。

对于更新,您必须修改select,以便它只返回一行一行(使用where子句)。

注意

如peterm所述,您的值列表中最多允许100个值。我不相信你会需要更多,但如果你愿意,那么你必须根据你的需要调整数字的生成。