获取MySQL数据库中最重复的类似字段

时间:2012-07-18 09:35:50

标签: php mysql sql levenshtein-distance

假设我们有一个数据库:

Actions_tbl:

--------------------------------------------------------
id | Action_name                              | user_id|
--------------------------------------------------------
1  |  John reads one book                     | 1     
2  |  reading the book by john                | 1
3  |  Joe is jumping over fire                | 2
4  |  reading another book                    | 2
5  |  John reads the book in library          | 1
6  |  Joe read a    book                      | 2
7  |  read a book                             | 3
8  |  jumping with no reason is Ronald's habit| 3 

Users_tbl:

-----------------------
user_id |    user_name |
-----------------------
1       |     John
2       |     Joe
3       |     Ronald
4       |     Araz
-----------------------

想知道我是否可以选择最重复的类似操作而不管用户是什么,并将我自己的user_name替换为当前用户!

阅读一本书,阅读书籍,阅读另一本书,在图书馆阅读书籍,阅读书籍和阅读书籍都是最常见的词语,因此与阅读书籍相关的员工重复了6次,系统应随机显示这六个句子中的一个,并用user_name替换Araz

喜欢:Araz读这本书

我的想法是

select replace(a.action_name , b.user_name) from actions_tbl a, user_tble b where a.user_id = b.user_id group_by

然后在php中逐个检查相似性

levenshtein()

但是这个根本没有表现!

假设我想为大型数据库和几个不同的表做同样的事情。 这会破坏我的服务器!!!

任何更好的IDEA?

http://www.artfulsoftware.com/infotree/queries.php#552中     levenshtein()函数是作为MySQL函数实现的,但首先,你认为它有足够的性能吗?然后,如何在我的情况下使用它? 也许一个自助加入面包车解决了这个问题,但我对sql并不是那么好!

* 类似的操作,是具有超过X%常用字词的操作


** 更多信息和说明:**

  1. 我只限于PHP和MySQL。

  2. 这只是一个例子,在我的真实项目中,动作是很长的段落。这就是性能问题的原因。真实的情况是:用户输入了几个项目的项目描述,那些数据可能太相似(用户会有相同的工作区域),我想自动填写(基于以前的填充)下一个项目的描述,节省时间。

  3. 如果您有任何 实用 解决方案,我将不胜感激。我检查了NLP相关的解决方案,虽然它们很有趣,但我认为它们中的很多都不准确并且可以使用PHP实现。

  4. 输出应该有意义,并且像所有其他项目一样是一个合适的段落。这就是为什么我想从之前的选择中选择。


  5. 感谢您的智力答案,如果能够对情况有所了解,我们非常感谢

2 个答案:

答案 0 :(得分:2)

您所谈论的是文本群集过程。您正在尝试查找类似的文本,并随意选择其中一个。我不熟悉使用这种形式的文本挖掘的任何数据库。

对于您所描述的内容,一种非常基本的文本挖掘技术可能会起作用。使用除用户名之外的所有单词创建术语 - 文档矩阵。然后使用奇异值分解来获得最大的奇异值和向量(这是相关矩阵的第一个主成分)。类似的活动应该沿着这条线聚集。

如果您的词汇量有限并且在表格中包含术语,则可以通过重叠的单词比例来衡量两个动作之间的距离。你有行动中所有单词的清单吗?

答案 1 :(得分:1)

首先,您必须决定是要将给定输入与所有现有文本进行比较,还是要对所有文本进行成对比较。你的问题要求后者,但你概述的应用程序听起来更像前者。

如果只比较一个输入和数据库,那么我希望levenshtein距离计算能够快到中等数据库大小。除非您存储关于文本库当前内容的某种形式的中间数据结构,否则可能没有多少方法可以使事情变得更快。为每个新输入重新计算任何东西都可能同样昂贵。

如果你想对每一对进行比较,那么每个对的levenshtein计算将花费太多时间。你必须设计一些其他的相似概念。我想到的第一件事就是suffix tree,它对一个词的不同形式有一定的弹性。您可以将所有段落插入该树中。在后缀树通常存储单个指针的情况下,您可能希望存储一对索引,一个标识数据库行,另一个表示该行文本中的位置。构建树之后,您可以遍历它以识别公共子串,并为相应的对增加一些相似性计数器。您将需要进行一些实验来调整此度量。在递增计数器之前,您可能希望对公共字符串施加最小长度。由于长文本具有更大的共同词的可能性,即使它们在语义上不相关,您可能必须以某种方式补偿长度。我怀疑有这样的规范方法。

term-document matrix方法suggested by Gordon听起来也很有趣,你也应该能够在PHP中实现它。即使根是相同的,这种方法也会对单词形式的变化敏感。另一方面,为数据库中存储的矩阵保留合适的矩阵可能更容易,并且在更新主文本表时保持该结构同步。这两种方法都与levenshtein距离有根本的区别:它们对整体秩序的关注度较低。我相信这对你的情况是一件好事,因为他们会考虑“约翰在湖里游泳后读一本书”的文字更像“在湖里游泳后,乔读了一本书”而不是levenshtein距离会。

你的例子表明你不仅想要对相似性进行排名,还要决定cluser边界,即。说“这些形成一个群体”和“那些属于不同的群体”。对此没有一个干净的截止,所以你也必须尝试启发式。除非总是选择最相似的文本,或者 k 大多数相似的文本,否则就足以满足您的应用需求。在任何情况下,我都会首先专注于相似度计算,并在稍后添加诸如用户名替换之类的内容。