【问题标题】:Calculate similarity between to records in MySQL计算MySQL中记录之间的相似度
【发布时间】:2013-11-03 06:08:34
【问题描述】:

我目前正在尝试弄清楚如何计算两条记录之间的相似度。我的第一条记录将来自停用的广告 - 所以我想找到例如关于某些 VARCHAR 字段相等性的 10 个最相似的广告。

我想不通的是,如果有任何 MySQL 函数,它可以以任何方式帮助我 - 或者我是否需要以某种奇怪的方式比较字符串?

编辑#1

相似性将由这些字段定义:

  • 职称(权重:50 %)

  • 含量(重量:40%)

  • 类别(重量:10 %)

编辑#2

我希望计算是这样的:

标题:在标题字段中匹配的单词(仅匹配 >2 个字母的单词)。

描述:在标题字段中匹配的单词(仅匹配 >2 个字母的单词)。

类别:匹配类别,如果不匹配则匹配权重较小的父类别:)

这样的等式可以是:

#1 是旧的、不活跃的帖子,#2 是活跃的帖子:

#2 标题在 #2 的 10 个单词中的 3 个单词与 #1 标题匹配。 这给出了 30 % 匹配 = 30 分。

#2 描述匹配 #1 描述,共 10 个单词,共 10 个 400 字。这给出了 4 % 的匹配 = 4 分。

#2 类别与#1 的类别不匹配,因此 0 % 匹配。那 给0分。

那么 #2 的总和将是 34 分。 :)

编辑#3

这是我的查询 - 但它不会返回不同的行,而是返回很多相同的行。

SELECT
            a.AdvertisementID as A_AdvertisementID,
            IF(a.Topic LIKE a2.Topic, 50, 0) + IF(a.Description LIKE a2.Description, 40, 0) + IF(a.Cate_CategoryID LIKE a2.Cate_CategoryID, 10, 0) as A_Score,
            a.AdvertisementID as A_AdvertisementID,
            a.Topic as A_Topic,
            LEFT(a.Description, 300) as A_Description,
            a.Price as A_Price,
            a.Type as A_Type
        FROM
            ".DB_PREFIX."A_Advertisements a2,
            ".DB_PREFIX."A_Advertisements a
        WHERE
            a2.AdvertisementID <> a.AdvertisementID
            AND
            a.AdvertisementID = :a_id
        ORDER BY
            A_Score DESC

【问题讨论】:

  • 你如何定义“相似性”?
  • 嘿 Rowland Shaw - 我试图在我的最新编辑中定义它。希望这是有道理的:)
  • 您是否在这些领域寻找平等?或者您是否知道如何计算两个字符串“相似程度”的度量?
  • Rowland:不,但我想,我想匹配单词。在整个高级查询中,我有可能不对 0-2 个字母的单词赋予任何值,而是匹配其余的单词。然后我想取匹配的总和并以百分比添加权重。我会在上面添加一个计算。

标签: mysql


【解决方案1】:

如果您可以从字面上比较您感兴趣的字段,您可以让 MySQL 使用 IF() 函数执行简单的评分计算,例如

select 
  foo.id,
  if (foo.title='wantedtitle', 50, 0) +
  if (foo.content='wantedcontent', 40, 0) +
  if (foo.category='wantedcategory', 10, 0) as score
from foo
order by score desc
limit 10

可以使用 like 来实现基本的“查找片段”

select 
  foo.id,
  if (foo.title like '%wantedtitlefragment%', 50, 0) +
  if (foo.content like '%wantedcontentfragment%', 40, 0) +
  if (foo.category like '%wantedcategoryfragment%', 10, 0) as score
from foo
order by score desc
limit 10

还有其他技术,但在 MySQL 中实施起来可能会很慢。例如,您可以计算两个字符串之间的Levenstein distance - 有关示例实现,请参阅this post

【讨论】:

  • 我可以用 LIKE 代替等号吗? :)
  • 是的,这对于基本的通配符来说就可以了。
  • 好的,现在我的问题是,我只知道旧广告 URL。我如何加入才能获得最高“分数”的 10 名? :)
  • 嘿,保罗,我已经改变了我的问题 - 你能帮忙编辑 #3 吗? :)
  • 确保对列进行索引,尤其是在使用 '%...%' 搜索时(在这种情况下,只有 FULLTEXT 索引才有用)。另外,我认为您在原始问题之上不断添加越来越多的请求是不公平的……这不是 SO 的工作方式。
猜你喜欢
  • 1970-01-01
  • 2011-07-16
  • 2017-08-22
  • 2012-03-11
  • 2017-03-19
  • 2021-11-18
  • 2019-08-05
相关资源
最近更新 更多