模式比较与mysql之间的两个表列



一个简单的问题是PHP中的preg_match和mysql查询中的like是一样的吗?

主要问题:

考虑以下是我的两个表表1和表2

表1 nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp表2

+--------------------------------------+++-------+------------------------------+|ID|型号||ID|型号|+-------+-------------------------++-------+------------------------------+|1|iPad2 WiFi 16GB ||1|iPad2 WiFi 16GB||2|iPhone 4S 16GB ||2|iPhone 4S 16GB||3|iPod Touch(第4代)8GB||3|iPod Touch第4代8GB|+-------+-------------------------++--------+-------------------------------+

现在我想做的是比较这两个表,因为你可以看到iPad 2 WiFi 16GBiPad2 WiFi 16GBiPod Touch(4th Gen)8GBiPod 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 

两个问题-描述是标准的(描述不变)还是用户输入的?如果它们是标准列,请添加一个整数列,并对该列进行比较。

如果它是由用户输入的,你的工作会更复杂,因为你正在寻找更模糊的搜索。我使用了一种双图搜索算法来对两个字符串之间的相似性进行排序,但这不能直接在mySQL中完成。

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

一旦我知道你想做什么,我很乐意详细说明。

第1版:好的,考虑到你的详细说明,你需要像我提到的那样进行模糊风格搜索。我使用了一种双图方法,它包括获取用户的每个条目,并将其拆分为2或3个字符的块。然后,我将这些块中的每一个存储在另一个表中,每个条目都键回到实际描述。

示例:

描述1:"快速向前跑"说明2:"短期向前">

如果你把每个字符分成两个字符块——"A"、"f"、"fa"、"as"、"t"。。。。。

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

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

或者,懒惰的替代方案是使用像亚马逊这样的云搜索服务,该服务将根据你提供的术语提供搜索……但不确定它们是否允许你不断添加新的描述来考虑,根据你的应用程序,这可能会有点贵(IMHO)。

R

关于二元图实现的另一篇SO文章-请参阅此SO二元图/模糊搜索

---按提问者详细说明更新——

首先,我假设你阅读了我提供的链接的理论。。其次,我会尽量让它与数据库无关,因为它不需要mySQL(尽管我使用它,而且它非常好用)

好的,所以只有在可能的匹配相对较小的情况下,bigram方法才能在内存阵列中进行制作/比较,否则它会很快受到表扫描性能的影响,就像没有索引的mysql表一样。因此,您将使用数据库的优势来帮助您进行索引。

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

然后,您需要制作另一个至少有三列的表——一列用于引用列,返回到另一个表的自动递增列(我们在下面称之为hd_id),第二列将是最多5个字符的varchar()(这将保存您的bigram块),我们在下面将其称为"bigram",第三列是自动递增列,称为b_id。该表将保存每个用户条目的所有bigram,并与整个条目绑定。您将需要对varchar列本身进行索引(或者在复合索引中按顺序排列)。

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

// 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;
}    

不要担心字符串中的空格——如果你考虑模糊搜索,它们实际上非常有用。

所以你得到了bigram,将它们输入到一个表中,通过一个索引列链接到表1中的整体文本。。。现在怎么办?

现在,每当您搜索诸如"我最喜欢搜索的术语"之类的术语时,您都可以使用php函数将其转换为一个bigram数组。然后使用它在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字符串引用留下来了——您可以使用内爆或从get_bigrams返回的数组上的任何内容,或者如果您喜欢的话,也可以参数化,将其从bigram函数中构造为逗号分隔的列表。

如果操作正确,上面的查询将根据您选择的二元图的长度返回最匹配的模糊搜索项。您选择的长度具有相对效力,这取决于您对整个搜索字符串的预期长度。

最后,上面的查询,只是给出了一个模糊匹配排名。您不仅可以比较匹配项,还可以通过比较匹配项与总体二元计数来进行改进,这将有助于消除长搜索字符串与短搜索字符串之间的偏差。我在这里停下来是因为在这个关键时刻,它变得更加特定于应用程序。

希望这能有所帮助!

R

相关内容

  • 没有找到相关文章

最新更新