2015-06-15 103 views
3

以逗号分隔的字符串存储数据不取决于我,它不是我可以在我的数据库中更改的东西,请耐心等待。我已经在线和在stackoverflow上进行了很多搜索,但是我找不到解决方案,如果甚至可以使用MySQL。如何用另一个表中的匹配值替换/更新列中每个字符串的所有实例?

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

这是我正在努力完成的。我有两个表,表1:

+------+-------------+ 
| 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  | 
+------+-------------------+ 
| ... | ...    | 
+------+-------------------+ 

我想从表2的相应值来代替从表1代码产生这样的结果:

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

您是否尝试过光标?您可以使用光标轻松更新每个单元格 –

回答

1

这应该这样做(请参阅下面的最后一个查询)。我已将逗号包含在连接中,因此,12之类的内容与id不匹配,例如212(例如)。

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 
+1

我试过你的方式,并在这里张贴的其他方式之一。我有两个工作,但我无法表达这种方式更简单。节省了大量的时间。谢谢! –

+1

不错。我认为concat('%,',t2.code,'%')需要concat('%,',t2.code,',%'),是不是?这是在追踪%之前添加逗号。 –

+0

@Karl Kieninger ......你是正确的先生。它最初编写的方式会得到错误的命中(例如,如果您正在查找id = 12并且有100,122个,您将在那里找不到该记录)。我将编辑答案以反映您的更正。 – John

0

而且这里我们看到一个完美的例子,为什么在数据库字段中使用逗号分隔的列表是一个糟糕的主意。他们比正确的关系表更难以操纵。

考虑到这一点,我会考虑首先将代码分成多个记录,然后做简单的基于替换,然后把它们放回到一起。基本上:

  1. 使用split function以产生具有1个记录每个项目/代码对临时表TMP1。

  2. 然后对从tmp1加入到table1的tmp1.code执行UPDATE。

  3. 最后使用GROUP_CONCAT将名称放在一起。

+0

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

相关问题