从表中选择包含另一个表中长字列表中任何单词的行

时间:2014-02-08 22:51:28

标签: mysql sql sorting match

每个财富1000强公司名称都有一张表:

FortuneList:

------------------------------------------------
|fid        |  coname                          |
------------------------------------------------
| 1         | 3m                               |
| 2         | Amazon                           |
| 3         | Bank of America                  |
| 999       | Xerox                            |
------------------------------------------------

我的时事通讯上有每个用户的第二张表:
MyUsers:

------------------------------------------------
|uid    |  name      | companyname             |
------------------------------------------------
| 1350  | John Smith |  my own Co              |
| 2731  | Greg Jones |  Amazon.com, Inc        |
| 3899  | Mike Mars  |  Bank of America, Inc   |
| 6493  | Alex Smith |  Handyman America       |
------------------------------------------------

如何提取每个为财富1000强公司工作的简报订阅者? (通过扫描我的整个MyUsers表,查找每个具有FortuneList表中任何一个coname的记录)

我希望输出拉:

------------------------------------------------
|uid   |  name       | companyname             |
------------------------------------------------
| 2731  | Greg Jones |  Amazon.com, Inc        |
| 3899  | Mike Mars  |  Bank of America, Inc   |
------------------------------------------------

(看看它如何在“Amazon.com,Inc”中找到“亚马逊”)

3 个答案:

答案 0 :(得分:1)

尝试使用此功能,该功能使用INNER JOINLIKE运算符和CONCAT

SELECT *
FROM MyUsers
INNER JOIN FortuneList
    ON FortuneList.coname LIKE CONCAT('%', MyUsers.companyname, '%)

(这不会使用您的全文索引,我试图找出如何在MATCH...AGAINST中使用JOIN。)

答案 1 :(得分:1)

如果您在Oracle中执行此操作,这将产生您想要的结果(使用示例数据):

with    fortunelist as(
        select 1 as fid, '3m' as coname from dual union all
        select 2, 'Amazon' from dual union all
        select 3, 'Bank of America' from dual union all
        select 999, 'Xerox' from dual
        )
        , myusers as(
        select 1350 as usrid, 'John Smith' as name, 'my own Co' as companyname from dual union all
        select 2731, 'Greg Jones', 'Amazon.com, Inc.' from dual union all
        select 3899, 'Mike Mars', 'Bank of America, Inc' from dual union all
        select 6493, 'Alex Smith', 'Handyman America' from dual 
        )
select  utl_match.jaro_winkler_similarity(myusers.companyname, fortunelist.coname) as sim
        , myusers.companyname
        , fortunelist.coname
from    fortunelist
        , myusers
where   utl_match.jaro_winkler_similarity(myusers.companyname, fortunelist.coname) >= 80

原因是,你所追求的2人的Jaro Winkler结果是87和95(分别是亚马逊和BOA)。您可以向上或向下碰撞查询中的80以使匹配阈值更高或更低。你去的越高,你所拥有的匹配就越少,但它们的可能性就越大。你去的越低,你所拥有的匹配就越多,但是你可能会遇到不匹配的比赛。例如,“Handyman America”与“Bank of America”= 73/100。因此,如果将其降低到70,则会使用示例数据得到误报。 Jaro Winkler通常用于人名,而不是公司名称,但是因为公司名称通常也是非常短的字符串,所以它可能对您有用。

我知道你把它标记为MySQL并且虽然这个函数不存在,但是从我读过的内容中,人们已经完成了为它创建自定义函数的工作: http://androidaddicted.wordpress.com/2010/06/01/jaro-winkler-sql-code/ http://dannykopping.com/blog/fuzzy-text-search-mysql-jaro-winkler

你也可以尝试字符串替换,例如。消除未找到匹配的常见原因(例如,一张桌子上有“公司”而另一张桌子没有)。

编辑2/10/14:

您可以按照以下步骤在MySQL(通过phpmyadmin)中执行此操作:

  1. 进入phpmyadmin,然后进入您的数据库并将此URL链接(下面)中的代码粘贴到SQL窗口中,然后点击Go。这将创建您需要在步骤2中使用的自定义函数。我不打算在此处粘贴函数的代码,因为它很长,也不是我的工作。它基本上允许你在MySQL中使用jaro winkler算法,就像你使用Oracle时使用utl_match一样。 http://androidaddicted.wordpress.com/2010/06/01/jaro-winkler-sql-code/

  2. 创建该函数后,运行以下SQL:

  3. -

    select  jaro_winkler_similarity(myusers.companyname, fortunelist.coname) as similarity
            , myusers.uid
            , myusers.name
            , myusers.companyname as user_co
            , fortunelist.coname as matching_co
    from    fortunelist
            , myusers
    where   jaro_winkler_similarity(myusers.companyname, fortunelist.coname) >= 80
    

    这应该会产生您正在寻找的确切结果,但就像我说你想要在那个SQL中使用80并且上下移动以便在避免误报之间取得良好平衡找到你想要找的匹配。

    我没有用于测试的MySQL数据库,所以如果遇到问题请告诉我,但这应该可行。

答案 2 :(得分:0)

使用LOCATE(因此没有索引):

select uid, name, companyname
from MyUsers JOIN FortuneList
WHERE LOCATE(coname, companyname) > 0