如何用另一个表中的匹配值替换/更新列中每个字符串的所有实例?

Posted

技术标签:

【中文标题】如何用另一个表中的匹配值替换/更新列中每个字符串的所有实例?【英文标题】:How do I replace/update all instances of every string in a column with matching values from another table? 【发布时间】:2015-06-15 18:35:43 【问题描述】:

以逗号分隔的字符串存储数据不取决于我,我无法在我的数据库中更改它,所以请耐心等待。我已经在网上和 *** 上进行了大量搜索,但我找不到解决方案,如果它甚至可以使用 mysql

我正在尝试用 table2 中的匹配值替换 table1 中每个唯一字符串的所有实例。我已经尝试过通配符、替换、更新、加入等,但我只是不确定如何使其工作。我知道一个解决方案是为每个字符串替换(),但 table2 有超过 200 行,所以这意味着嵌套超过 200 次。

这就是我想要完成的。我有两张桌子,table1:

+------+-------------+
| Item | Code        |
+------+-------------+
| 1    | 614         |
+------+-------------+
| 2    | 212,614,415 |
+------+-------------+
| 3    | 212,303     |
+------+-------------+
| ...  | ...         |
+------+-------------+

和表2:

+------+-------------------+
| Code | Name              |
+------+-------------------+
| 614  | Columbus, OH      |
+------+-------------------+
| 212  | New York, NY      |
+------+-------------------+
| 415  | San Francisco, CA |
+------+-------------------+
| 303  | Ft. Worth, TX     |
+------+-------------------+
| ...  | ...               |
+------+-------------------+

我想用 table2 中的相应值替换 table1 中的代码以产生此结果:

+------+---------------------------------------------+
| Item | Code                                        |
+------+---------------------------------------------+
| 1    | Columbus, OH                                |
+------+---------------------------------------------+
| 2    | New York, NY,Columbus, OH,San Francisco, CA |
+------+---------------------------------------------+
| 3    | New York, NY,Ft. Worth, TX                  |
+------+---------------------------------------------+
| ...  | ...                                         |
+------+---------------------------------------------+

【问题讨论】:

你试过游标吗?您可以使用光标轻松更新每个单元格 【参考方案1】:

应该这样做(请参阅下面的最后一个查询)。我在连接中包含了逗号,这样 12 之类的 id 与您拥有的位置和 212 的 id 不匹配(例如)。

drop table if exists table1;

drop table if exists table2;

create table table1(
    item int,
    code varchar(64)
);

create table table2(
    code int,
    name varchar(64)
);

insert into table1 values (1, '614');
insert into table1 values (2, '212,614,415');
insert into table1 values (3, '212,303');

insert into table2 values(212, 'New York, NY');
insert into table2 values(303, 'Ft. Worth, TX');
insert into table2 values(415, 'San Francisco, CA');
insert into table2 values(614, 'Columbus, OH');

select * from table1

+ --------- + --------- +
| item      | code      |
+ --------- + --------- +
| 1         | 614       |
| 2         | 212,614,415 |
| 3         | 212,303   |
+ --------- + --------- +
3 rows

select * from table2

+ --------- + --------- +
| code      | name      |
+ --------- + --------- +
| 212       | New York, NY |
| 303       | Ft. Worth, TX |
| 415       | San Francisco, CA |
| 614       | Columbus, OH |
+ --------- + --------- +
4 rows

select 
    t1.item,
    t2.name
from
    table1 t1 join table2 t2 on (
        t1.code = t2.code
        or t1.code like concat(t2.code, ',%')
        or t1.code like concat('%,', t2.code, ',%')
        or t1.code like concat('%,', t2.code)
    )
order by t1.item

+ --------- + --------- +
| item      | name      |
+ --------- + --------- +
| 1         | Columbus, OH |
| 2         | Columbus, OH |
| 2         | New York, NY |
| 2         | San Francisco, CA |
| 3         | Ft. Worth, TX |
| 3         | New York, NY |
+ --------- + --------- +
6 rows

编辑: 或者如果您想像这样保持数据非规范化:

select 
    t1.item,
    group_concat(t2.name)
from
    table1 t1 join table2 t2 on (
        t1.code = t2.code
        or t1.code like concat(t2.code, ',%')
        or t1.code like concat('%,', t2.code, ',%')
        or t1.code like concat('%,', t2.code)
    )
group by t1.item
order by t1.item

+ --------- + -------------------------- +
| item      | group_concat(t2.name)      |
+ --------- + -------------------------- +
| 1         | Columbus, OH               |
| 2         | Columbus, OH,New York, NY,San Francisco, CA |
| 3         | Ft. Worth, TX,New York, NY |
+ --------- + -------------------------- +
3 rows

【讨论】:

我尝试了您的方式以及此处发布的其他方式之一。我让两者都工作,但我无法表达这种方式有多简单。节省了大量时间。谢谢! 不错。我认为 concat('%,', t2.code, '%') 需要是 concat('%,', t2.code, ',%'),对吗?那就是在结尾的 % 之前添加一个逗号。 @Karl Kieninger ...您说得对,先生。按照最初的编写方式,您会得到错误的命中(例如,如果您正在寻找 id=12 并且有 100,122,那么您会在不应该的地方获得该记录)。我将编辑答案以反映您的更正。【参考方案2】:

在这里,我们看到了一个完美的例子,说明为什么在 DB 字段中使用逗号分隔的列表是一个坏主意。它们比适当的关系表更难操作。

考虑到这一点,我会考虑首先将代码拆分为多个记录,然后进行简单的基于集合的替换,然后将它们重新组合在一起。本质上:

    使用 split function 创建一个临时表 tmp1,其中每个项目/代码对有 1 条记录。

    然后对连接到 table1 的 tmp1 中的 tmp1.code 执行 UPDATE。

    最后使用GROUP_CONCAT 将名称重新组合在一起。

【讨论】:

我花了很多额外的研究来弄清楚拆分函数/存储过程/光标部分,但这实际上是我完成工作的方式。谢谢!

以上是关于如何用另一个表中的匹配值替换/更新列中每个字符串的所有实例?的主要内容,如果未能解决你的问题,请参考以下文章

在MYSQL中如何用一个字段的值替换另一个字段的值

如何用同一数据框中其他列的实际列值替换一列中的字符串值?

如何用 0 替换 varchar 列中的所有非数字值

如何用 NA 替换列中的字符串值并将列转换为浮点数?

用另一个表中同一列的值替换列中的字符串值

如何用另一个表中的另一列替换一列数据?