3

一个简单的问题是preg_matchPHP 和likemysql 的查询是一样的吗?

主要问题:

考虑以下是我的两个表 table1 和 table2

表 1                                                                       表 2

+--------+-------------+ +--------+------ ------------------------------------+
| 身份证 | 型号 | | 身份证 | 型号 |
+--------+-------------+ +--------+------ ------------------------------------+
| 1 | iPad 2 WiFi 16GB | | 1 | iPad2 WiFi 16GB |
| 2 | iPhone 4S 16GB | | 2 | iPhone4S 16GB |
| 3 | iPod Touch(第 4 代)8GB | | 3 |iPod Touch 第 4 代 8GB |
+--------+-------------+ +--------+------ ------------------------------------+

现在我想做的是比较这两个表,如您所见iPad 2 WiFi 16GB,and iPad2 WiFi 16GBor iPod Touch(4th Gen)8GBandiPod Touch 4th Generation 8GB两者都相同,但它不显示我是否输入查询where Table1.model = Table2.model,因为它们不完全匹配。我想做的是通过使用like或任何其他方式将这些行与mysql查询进行比较,以便比较两个相似的表行。请让我知道如何编写这样的 sql 查询。

我尝试了以下 sql 查询,但它没有返回所有行,就像它没有返回上面示例中提到的那些类型的行一样。

SELECT table1.model as model1, table2.model as model2
FROM table1,table2 WHERE table1.model REGEXP table2.model 
4

1 回答 1

1

两个问题 - 描述是标准的(描述不会改变)还是由用户输入?如果它们是标准的,则添加一个整数列并在此列上进行比较。

如果它是由用户输入的,那么您的工作会更加复杂,因为您正在寻找更模糊的搜索。我使用二元搜索算法对两个字符串之间的相似度进行排序,但这不能直接在 mySQL 中完成。

代替模糊搜索,您可以使用 LIKE,但如果您最终将“%”放在搜索词的开头,它的效率仅限于执行表扫描。此外,这意味着您可以在您选择的子字符串部分上获得匹配,这意味着您需要提前知道子字符串。

一旦我知道您要做什么,我会很乐意详细说明。

EDIT1:好的,鉴于您的详细说明,您将需要进行模糊样式搜索,正如我所提到的。我使用二元组方法,该方法涉及获取用户输入的每个条目并将其拆分为 2 或 3 个字符的块。然后我将这些块中的每一个存储在另一个表中,每个条目都键入回实际描述。

例子:

描述1:“快速向前跑” 描述2:“快速向前跑”

如果你将每个分成 2 个字符块 - 'A'、'f'、'fa'、'as'、'st'......

然后,您可以比较与两个字符串匹配的 2 个字符块的数量,并获得一个“分数”,这将意味着两者之间的准确性或相似性。

鉴于我不知道您使用的是哪种开发语言,我将省略实现,但这是需要在 mySQL 中不明确地完成的事情。

或者懒惰的选择是使用像亚马逊这样的云搜索服务,它会根据你给它的术语提供搜索……但不确定它们是否允许你不断添加新的描述来考虑,并且根据你的应用程序,它可能有点贵(恕我直言)。

R

有关二元组实现的另一篇 SO 帖子 - 请参阅此SO 二元组/模糊搜索

---根据提问者的详细说明更新---

首先,我假设您阅读了我提供的链接上的理论..其次,我会尽量保持它与 DB 无关,因为它不需要 mySQL(尽管我使用它,它的工作原理不止于此)美好的)

好的,所以只有当可能的匹配项相对较小时,bigram 方法才能在创建/比较内存中的数组时正常工作,否则它会很快受到表扫描性能的影响,例如没有索引的 mysql 表。因此,您将利用数据库的优势来帮助您进行索引。

您需要一张表格来保存用户输入的“术语”或您要比较的文本。最简单的形式是一个有两列的表,一个是一个唯一的自增整数,它将被索引,我们将在下面调用 hd_id,如果字符串很短,第二个是 varchar(255),如果可以,则为 TEXT变长 - 你可以随意命名。

然后,您需要创建另一个至少包含三列的表 - 一个用于引用列返回到另一个表的自动递增列(我们将在下面将此称为 hd_id),第二个将是 varchar()最多说 5 个字符(这将保存你的二元组),我们将在下面称之为“二元组”,第三个是下面称为 b_id 的自动递增列。该表将保存每个用户条目的所有二元组,并与整个条目相关联。您需要自己索引 varchar 列(或在复合索引中按顺序排列)。

现在,每次用户输入您要搜索的术语时,您需要在第一个表中输入该术语,然后将其分解为二元组,并使用对整个术语的引用将每个块输入到第二个表中第一个表来完成关系。这样,您在 PHP 中进行剖析,但让 mySQL 或任何数据库为您进行索引优化。在二元组阶段存储表 1 中为计算阶段生成的二元组数量可能会有所帮助。以下是 PHP 中的一些代码,可让您了解如何创建二元组:

// split the string into len-character segments and store seperately in array slots
function get_bigrams($theString,$len)   
{
   $s=strtolower($theString);
   $v=array();
   $slength=strlen($s)-($len-1);     // we stop short of $len-1 so we don't make short chunks as we run out of characters

   for($m=0;$m<$slength;$m++)
   {
      $v[]=substr($s,$m,$len);
   }
   return $v;
}    

不要担心字符串中的空格——如果您考虑模糊搜索,它们实际上真的很有帮助。

所以你得到二元组,将它们输入一个表格,通过和索引列链接到表 1 中的整体文本......现在怎么办?

现在,每当您搜索诸如“我最喜欢的要搜索的术语”之类的术语时,您都可以使用 php 函数将其转换为二元数组。然后,您可以使用它在二元表 (2) 上创建 SQL 语句的 IN (..) 部分。下面是一个例子:

select count(b_id) as matches,a.hd_id,description, from table2 a
inner join table1 b on (a.hd_id=b.hd_id)
where bigram in (" . $sqlstr . ")
group by hd_id order by matches desc limit X

我将 $sqlstr 保留为 PHP 字符串引用 - 您可以使用 implode 或从 get_bigrams 返回的数组上的任何内容,将它自己构造为与 bigram 函数的逗号分隔列表,或者如果您也喜欢参数化。

如果正确完成,上面的查询会根据您选择的二元组的长度返回最匹配的模糊搜索词。您选择的长度具有基于您预期的整个搜索字符串长度的相对效力。

最后 - 上面的查询只是给出了一个模糊匹配等级。您不仅可以比较匹配项,还可以比较匹配项与整体二元组计数来进行改进和增强,这将有助于消除长搜索字符串与短字符串相比的偏差。我已经停在这里了,因为在这个时刻它变得更加特定于应用程序。

希望这可以帮助!

R

于 2012-11-16T13:13:02.733 回答