4

考虑下面的推文表

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 中循环遍历它以进行大规模替换。

感谢您的帮助:-)

4

3 回答 3

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匹配,然后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像这样定义的表在哪里:

CREATE TABLE Pattern
    (pattern varchar(50), replacestr varchar(50));

INSERT INTO Pattern
    (pattern, replacestr)
VALUES
    ('% {0} %', ' {0} '),
    ('{0} %', '{0} '),
    ('% {0}', ' {0}');

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

于 2012-04-23T19:37:48.050 回答
1

难道没有更好的方法来捕获所有可能的“alcoa inc”实例吗?

REGEX(正则表达式)搜索。查看官方mysql REGEX文档以获取更多信息。

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

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

 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');

这只是一个示例来说明一种可能的方式,您必须根据您的要求和特定上下文对其进行调整。

于 2012-04-23T19:40:41.600 回答
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}'
于 2012-04-23T19:44:45.973 回答