一个简单的问题是PHP中的preg_match
和mysql查询中的like
是一样的吗?
主要问题:
考虑以下是我的两个表table1和table2
表1 表2
+-------+-------------------------+ +-------+------------------------------+ | ID | Model | | ID | Model | +-------+-------------------------+ +-------+------------------------------+ | 1 | iPad 2 WiFi 16GB | | 1 | iPad2 WiFi 16GB | | 2 | iPhone 4S 16GB | | 2 | iPhone4S 16GB | | 3 | iPod Touch(4th Gen)8GB | | 3 |iPod Touch 4th Generation 8GB | +-------+-------------------------+ +-------+------------------------------+
现在我要做的是比较这两个表,因为你可以看到iPad 2 WiFi 16GB
和iPad2 WiFi 16GB
或iPod Touch(4th Gen)8GB
和iPod 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
答案 0 :(得分:1)
两个问题 - 描述标准(描述不会改变)或是由用户输入?如果它们是标准的,请添加一个整数的列并在此列上进行比较。
如果由用户输入,您的工作会更复杂,因为您正在寻找更模糊搜索的内容。我使用二元搜索算法对两个字符串之间的相似性进行排序,但这不能直接在mySQL中完成。
代替模糊搜索,你可以使用LIKE,但如果你最终选择了'%'%,那么它的效率仅限于进行表格扫描。在搜索词的开头。此外,它暗示您可以在您选择的子字符串部分上获得匹配,这意味着您需要提前知道子字符串。
一旦我知道你想要做什么,我会很乐意详细说明。
EDIT1:好的,鉴于您的详细说明,您需要进行模糊样式搜索,如我所述。我使用bi-gram方法,它涉及用户创建的每个条目并将其拆分为2或3个字符的块。然后,我将每个块存储在另一个表中,每个条目都键入到实际描述中。
示例:
描述1:"快速前进" 说明2:"短暂的前进"
如果你将每个分成两个char块 - ' A',' f',' fa',' as',' st' .....
然后你可以比较两个字符串匹配两个字符串的数量,得到一个"得分"这将意味着两者之间的准确性或相似性。
鉴于我不知道您正在使用哪种开发语言,我会将实现保留下来,但这需要在mySQL中明确完成。
或者懒惰的替代方案是使用像亚马逊这样的云搜索服务,根据您提供的条款提供搜索...不确定它们是否允许您不断添加新的描述以供考虑,并且取决于您的应用程序,它可能有点贵(恕我直言)。
[R
关于bigram实现的另一篇SO帖子 - 请参阅此SO bigram / fuzzy search
---每个提问者的详细阐述---
首先,我假设您在我提供的链接上阅读理论。其次,我会尝试尽可能保持数据库不可知,因为它不需要mySQL(尽管我使用它,它的工作效果非常好)
好的,因此只有在可能的匹配相对较小的情况下,bigram方法才能在内存数组中进行/比较,否则它会像没有索引的mysql表那样快速地遇到表扫描性能。因此,您将使用数据库优势来帮助为您编制索引。
您需要的是一个用于保存用户输入的表格"条款"或者您希望比较的文字。最简单的形式是一个包含两列的表,一个是唯一的自动增量整数,它将被索引,我们将在下面调用hd_id,第二个是varchar(255),如果字符串很短,或者TEXT if它们可以变长 - 你可以随意命名。
然后,您需要创建另一个至少有三列的表 - 一个用于参考列,返回到另一个表的自动递增列(我们将在下面调用此hd_id ),第二个是最多5个字符的varchar()(这将保留你的二元组块),我们称之为#34; bigram"下面,第三个是一个名为b_id的自动递增列。此表将包含每个用户条目的所有bigrams并绑定到整个条目。您将要自己索引varchar列(或者首先在复合索引中按顺序索引)。
现在,每当用户输入您要搜索的术语时,您需要在第一个表格中输入术语,然后将术语解析为双字母组合并使用引用将每个块输入到第二个表格中在第一个表中的术语来完成关系。这样,您就可以在PHP中进行解剖,但让mySQL或其他数据库为您进行索引优化。在bigram阶段,在计算阶段存储表1中制作的双字母组的数量可能会有所帮助。下面是PHP中的一些代码,可以让您了解如何创建bigrams:
// 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中的整体文本......现在是什么?
现在每当你搜索一个术语,例如&#34;我最喜欢的术语来搜索&#34; - 你可以使用php函数将它变成一个bigrams数组。然后使用它在您的bigram表(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函数自己构建一个逗号分隔列表。如果你愿意的话。 / p>
如果操作正确,上面的查询将返回最匹配的模糊搜索项,具体取决于您选择的两字组的长度。您选择的长度具有基于整个搜索字符串的预期长度的相对效率。
最后 - 上面的查询,只给出模糊匹配等级。您可以通过比较不仅仅是匹配,而是通过比较整体二元组计数来进行游戏和增强,这将有助于消除长字符串与长字符串相比的偏差。我已经在这里停留了,因为在这个时刻,它变得更具针对性。
希望这有帮助!
[R