【问题标题】:Get the most repeated similar fields in MySQL database获取 MySQL 数据库中重复次数最多的相似字段
【发布时间】:2012-07-18 09:35:50
【问题描述】:

假设我们有一个类似的数据库:

Actions_tbl:

-------------------------------------------------- ------ 编号 |动作名称 |用户ID| -------------------------------------------------- ------ 1 |约翰读一本书 | 1 2 |阅读约翰的书| 高分辨率照片| CLIPARTO 1 3 |乔跳过火| 2 4 |读另一本书| 2 5 |约翰在图书馆看书 | 1 6 |乔读了一本书 | 2 7 |读一本书| 3 8 |无缘无故跳是罗纳德的习惯| 3

Users_tbl:

---------------------- 用户 ID |用户名 | ---------------------- 1 |约翰 2 |乔 3 |罗纳德 4 |阿拉兹 ----------------------

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

读一本书,读一本书,再读一本书,在图书馆读一本书,读一本书和读一本书是最常见的单词,所以与读书相关的工作人员重复了6次,我的系统应该随机显示这六个句子之一,并将 Araz 替换为 user_name

赞:阿拉兹看书

我的想法是

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()

但是这个根本没有性能!

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

还有更好的想法吗?

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

* 相似动作,是有超过 X% 常用词的动作


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

  1. 我仅限于 PHP 和 MySQL。

  2. 这只是一个例子,在我的实际项目中,动作是长段落。这就是为什么性能是一个问题。真实场景是:用户为多个项目输入了其项目的描述,这些数据可能过于相似(用户将有相同的工作领域),我想自动填写(基于之前的填写)下一个项目的描述,以节省时间。

  3. 如果您能提供任何实用解决方案,我将不胜感激。我查了 NLP 相关的解决方案,虽然很有趣,但我觉得很多都不是很准确,可以用 PHP 实现。

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


感谢您的智慧回答,如果您能对情况有所了解,我们将不胜感激

【问题讨论】:

标签: php mysql sql levenshtein-distance


【解决方案1】:

您所说的是文本聚类过程。您正试图找到相似的文本片段,并随意选择其中之一。我不熟悉任何进行这种形式的文本挖掘的数据库。

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

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

【讨论】:

  • 感谢建议,这个表格只是一个示例,实际上我有一个包含长段落的表格,每个段落可以超过10行,表格会有很多!您认为列出所有单词并按照您所说的去做是否实用? PHP中有没有示例?
  • 另外我正在实现某种自动填充,因此系统可以根据用户之前提供的数据来填充表单。
  • 你有一个比通常由数据库直接解决的更复杂的问题。你需要一个应用程序。例如,如果您使用 SAS,您可能会查看 SAS Text Miner。如果您有表格列表,并且想要找到最接近每个段落的表格,您可以使用词袋方法来做到这一点。在任何情况下,您都会遇到关系数据库无法解决的问题(尽管它们可以成为解决方案的一部分)。
  • 问题是我仅限于 MySQL 和 PHP :(
【解决方案2】:

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

如果您仅将单个输入与您的数据库进行比较,那么我希望 levenshtein 距离计算在中等数据库大小的情况下足够快。除非您存储有关文本库当前内容的某种形式的中间数据结构,否则可能没有什么方法可以使事情变得更快。为每个新输入重新计算任何东西的成本可能同样高。

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

term-document matrix 方法suggested by Gordon 听起来也很有趣,您也应该能够在 PHP 中实现它。即使词根相同,这种方法也会对词形的变化更加敏感。另一方面,为存储在数据库中的矩阵保留一个合适的矩阵,并在更新主文本表时保持该结构同步可能会更容易。这两种方法都与 levenshtein distance 有根本的区别:它们不太关心整体顺序。我相信这对你来说是件好事,因为他们会认为“约翰在湖里游泳后读了一本书”比“在湖里游泳后,乔读了一本书”更类似于 levenshtein distance会的。

您的示例表明,您不仅要对相似性进行排名,还要确定聚类边界,即说“这些形成一个群体”和“那些属于不同的群体”。对此没有明确的界限,因此您还必须尝试使用​​启发式方法。除非总是选择最相似的文本,或者 k 个最相似的文本,对于您的应用程序来说就足够了。无论如何,我会先专注于相似度计算,然后再添加用户名替换等内容。

【讨论】:

  • 感谢您的评论,是的,我想比较表中的所有行以找到最常见的行,然后选择其中一个作为输出。
  • 在这里,不需要适当的排名(与stackoverflow.com/questions/11609348/… 不同)我们可以应用您在此处提到的相同内容。检查所有行(通过左连接)并通过运行过程查找相似行的查询(如果行相似,则返回 true)。问题是那个程序怎么写?我无法制作字典,因为单词不受限制,我无权访问插入事件(我的应用程序是插件)使用另一个应用程序输入数据
  • 关于选择,从常见的相似行中随机选择就足够了。 SELECT * FROM table ORDER BY RAND() LIMIT 0,1;其中 table 是最常见的相似行。 [读一本书|看书|读另一本书|在图书馆看书|读一本书|读一本书]在我们的例子中。
猜你喜欢
  • 1970-01-01
  • 2021-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-21
  • 1970-01-01
  • 2016-02-08
  • 2019-04-14
相关资源
最近更新 更多