批量替换MySQL中的字符串

时间:2012-04-23 19:19:20

标签: mysql sql

考虑下面的推文表

id  tweet
------------------------------------------------------
1   alcoa inc stock analysis
2   bullrider has added alcoa inc to portfolio
3   caterpillar annual results
4   more at http://bit.ly/d3423 on caterpillar
5   making apple inc profits

我想用指定的标签替换公司名称,如下所示:

id  tweet
------------------------------------------------------
1   {COMPANY|AA} stock analysis
2   bullrider has added {COMPANY|AA} to portfolio
3   {COMPANY|CAT} annual results
4   more at http://bit.ly/d3423 on {COMPANY|CAT}
5   making {COMPANY|AAPL} profits

我现在有以下查询:

UPDATE
  tweets
SET
  tweet = REPLACE(tweet, 'alcoa inc', '{COMPANY|AA}')
WHERE
  tweet LIKE '% alcoa inc %'
OR
  tweet LIKE 'alcoa inc %'
OR
  tweet LIKE '% alcoa inc'

但我有两个问题:

  1. 是否有更好的方法来捕捉所有可能的“Alcoa inc”实例?
  2. 在SQL中是否可以为多个替换编写一种数组(在SQL中,因此不能在PHP中编写)。这里。我的意思是在SQL中定义类似array("alcoa inc" => "{COMPANY|AA}", "caterpillar" => "{COMPANY|CAT}", "apple inc" => "{COMPANY{AAPL}")的东西,并在SQL中循环它以进行批量替换。
  3. 感谢您的帮助: - )

3 个答案:

答案 0 :(得分:3)

您可以尝试在表格中存储代码和公司列表,并使用如下查询:

select
    case
        when c.ticker is not null then
            replace(t.tweet, c.name,
                    concat('{COMPANY|',c.ticker,'}'))
        else t.tweet
    end as tweet
from
    tweets t
left join
    company c
        on
            t.tweet like concat('% ', c.name, ' %')
        or
            t.tweet like concat(c.name, ' %')
        or
            t.tweet like concat('% ', c.name)
group by
    t.id

唯一的缺点是这个解决方案不会处理两家公司的名字出现在同一条推文中的情况。其中只有一个会被替换。

演示:http://www.sqlfiddle.com/#!2/8da9d/2


编辑:正如@Mario所指出的,如果同一个字符串中有多个实例,匹配可能会导致错误的替换。例如,将字符串I have a redapple from apple与替换apple一起使用会产生字符串I have a red{COMPANY|AAPL} from {COMPANY|AAPL},因为第二个apple会触发LIKE匹配,然后是{{ 1}}替换每场比赛。我有一个更新的查询,通过从表中读取匹配的字符串来处理这种情况:

REPLACE

select case when p.ticker is not null then replace(t.tweet, replace(p.replacestr, '{0}', p.name), replace(p.replacestr, '{0}', concat('{COMPANY|',p.ticker,'}'))) else t.tweet end as tweet from tweets t left join (select * from pattern,company) p on t.tweet like replace(p.pattern, '{0}', p.name); group by t.id 是一个如下定义的表:

Pattern

演示:http://www.sqlfiddle.com/#!2/c71d4/3

答案 1 :(得分:1)

  

难道没有更好的方式来捕捉所有可能的" Alcoa inc"实例

REGEX(Reqular Expression)搜索。查看官方mysql REGEX文档以获取更多信息。

  

在SQL中是否可以为多个编写一种数组   替换(在SQL中,因此不在PHP中)。这里。我的意思是定义   在SQL中类似于数组(" Alcoa inc" =>" {COMPANY | AA}",   "毛虫" => " {COMPANY | CAT}"," apple inc" => " {COMPANY {AAPL}")和   在SQL中循环遍历它以进行批量替换。

是的,您可以创建一个特定的表来存储key->值字典,然后从中获取值,例如:

 table : dictionary
+----------+-----------------------+---------------+
| name     | pattern               | replacement   |
+----------+-----------------------+---------------+
|alcoa inc | [[:space:]]+alcoa inc |{COMPANY|AA}   |
|apple inc | apple inc.*           |{COMPANY{AAPL} |

您可以使用以下查询进行更新,例如:

UPDATE tweets SET tweets = REPLACE(tweet, 'alcoa inc', '{COMPANY|AA}') 
WHERE  tweet RLIKE (SELECT pattern FROM dictionary WHERE name = 'alcoa inc');

这只是一个说明可能方式的示例,您必须根据您的要求和特定背景进行调整。

答案 2 :(得分:0)

这样做的一种方法是使用存储过程:

CREATE PROCEDURE UpdateTweetsWithCompany
    @CompanyName varchar(255) = 'alcoa inc',
    @ReplaceValue varchar(255) = '{COMPANY|AA}'
AS
BEGIN
    UPDATE
      tweets
    SET
      tweet = REPLACE(tweet, @CompanyName, @ReplaceValue)
    WHERE
      tweet LIKE '% ' + @CompanyName + ' %'
    OR
      tweet LIKE @CompanyName + ' %'
    OR
      tweet LIKE '% ' + @CompanyName
END

然后打电话给它,有点像这样:

EXEC UpdateTweetsWithCompany 'alcoa inc', '{COMPANY|AA}'