PHP怎么实现数据模糊查询 模糊匹配的3种SQL写法示例

你好,你的总结很完美,但我还是要给你讲讲我上次踩坑的经历。

上周,一位客户问我为什么LIKE模糊查询这么慢。
我一看,哦,数据库表里有几万条数据,他直接用LIKE'%keyword%'。
我直接告诉他。
这个性能低得惊人,基本相当于全表扫描。

你是对的。
您必须使用 mysqli_real_escape_string() 进行转义。
否则直接发送SQL注入。
但仅靠逃跑是不够的。
请小心。
在关键字前添加 % 可以防止索引被使用。
例如,如果使用LIKE '%shoe%'在产品库中搜索product_name字段,MySQL不知道索引在哪里,因此只能一一扫描。

上次我优化了它们并最终得到: 1 . 重写查询。
要求他们使用 LIKE 'keyword%' 而不带前导 %,以便他们可以使用索引。
2 、添加全文索引:如果产品名称全是中文,则直接添加MySQL全文索引。
比赛...对抗非常好。
3 .添加缓存:常用查询结果存储在Redis中。
对于客户经常搜索的词,例如“运动鞋”,可以直接返回缓存数据,而不必每次都检查数据库。

你提到的 sounex() 和 diffrence() 看起来很有趣,但我没有太多使用它们。
仅当拼音相似时才使用拼音表 + LIKE 或直接在前端添加拼音框。
至于Elasticsearch/Solr...我仍然认为有点矫枉过正。
他们的系统设置起来比添加索引更麻烦。

反正简单查询就用LIKE就可以了,但是如果要做简单查询就需要重写查询+添加索引+添加缓存。
正则表达式 ^[a-zA-Z]+$ 很棒,但您需要验证客户输入的所有内容。
例如,使用 preg_match() 排除特殊字符。
否则,如果有人输入“OR 1 =1 ”,数据库就会爆炸。

SQL查询中“等于号”为何导致“模糊”匹配?

天哪,我最近帮助一个朋友解决了一个数据库问题,这真是太荒谬了。
他说,当他编写SQL查询时,他最初想使用等号(=)来查找该数据。
但他发现有些数据与迹象根本不相符,几乎就像玩捉迷藏一样。
我很困惑。
这个SQL查询不应该等同于搜索相同款式的衣服吗?款式相同扣分、颜色相同扣分吗?为什么变得这么不清楚?
仔细一看发现问题出在字段类型上。
例如,一个字段可以是字符类型,而另一字段可以是整数类型。
一旦两种类型进行比较,数据库就会自动开始执行“隐式类型转换”。
这就像一个人突然换衣服一样。
本来是A款,一改就变成了B款。
你还认得它吗?
我记得2 01 9 年左右帮助一家公司进行数据迁移,当时这是一个问题。
有一个字符 ID 字段和一个整数顺序 ID 字段必须相关。
最初,我们还使用等号(=)进行比较。
结果我们发现有些订单数据不匹配。
显然是同一条记录,但数据库确定它不匹配。
查了一下,发现字符ID字段前面有几个空格,但是整数ID字段没有空格,所以转换后它们并不相同。

解决办法其实很简单。
合并字段类型,例如将字符类型更改为整数类型,反之亦然。
或者,使用显式类型转换,例如使用 CAST 或 CONVERT 函数指定转换规则。
这样数据库就不会再偷偷换你的衣服了。

校对规则也很重要。
例如,默认情况下字符比较不区分大小写,这很容易导致错误的决定。
因此,如果需要区分大小写,则必须指定相应的排序规则。

这个坑我已经掉过好几次了。
总结一下,在设计表的时候,相关字段的类型一定要统一,我的经验可以总结如下。
编写查询时请注意字段类型转换问题。
如果无法避免类型转换,请使用显式转换并检查更正规则。
这样,您在使用等号(=)查找数据时就可以更加准确可靠。

如何使用like进行模糊匹配?

嘿兄弟,你最近在忙什么?我研究数据库已经有一段时间了。
要知道,有时候要在海量的数据中找出一根针,就像大海捞针一样。
例如,有一天我必须在一批型号中查找带有“PSM2 4 W”的设备的信息,这并不容易。
我用SQL编写了一个查询,并使用了LIKE关键字,这样我就可以过滤符合条件的数据。

我写的是:从 CK_ATE 中选择 top1 0,其中型号为“PSM2 4 W%”。
这次你明白了吗?我这里用的是PSM2 4 W%,也就是说只要型号字段中有以“PSM2 4 W”开头的,我就能找到。
这个伎俩非常有效。
很快就找到了1 0条符合条件的数据。

其他时候,你只能知道中间部分,这很简单。
例如,如果我想找到模型中间带有“2 4 W”的设备,我会编写 select TOP 1 0 from CK_ATE,其中模型将类似于“%2 4 W%”。
这样,无论“2 4 W”位于何处,都可以找到。

再比如,如果你只知道结局,就用LIKE。
我发现了一批型号以“-R-FA1 ”结尾的设备,因此我从 CK_ATE 中选择了前 1 0 个,其中型号类似于“%-R-FA1 ”。
这样,不管前面是什么,只要是以“-R-FA1 ”结尾的,给我找一下。

我已经使用这个技巧很多年了,而且很有效。
不过说起来,数据库确实很复杂,有时候还得根据实际情况调整查询语句。
我对这个领域非常熟悉。
如有任何问题,所以就问我吧。

模糊匹配地址数据的实用教程

PostgreSQL 在处理地址数据时确实很烦人。
特别是对于那些非标准地址,模糊匹配就显得非常关键。
pg_trgm扩展非常好用,下面我就给大家上手体验一下。

1 .安装插件
1 .订购此: sql CREATE EXTENSION pg_trgm;
必须具有管理员权限才能运行。
安装后,检查: sql SELECT FROM pg_extension WHERE extname = 'pg_trgm';
查看是否返回任何结果。
如果是,则说明已安装。

2 主要功能
1 .相似度()函数: sql SELECT 相似度('阿本德松', '阿本德松酒店'); -
返回0.8 左右 SELECT 相似度('Abendsonne', 'Undine'); -
返回大约0.1
这个函数非常直观。
两个字符串越相似,得分越高,介于 0 和 1 之间。

2 . % 运算符: sql SELECT address_string FROM 地址 WHERE address_string % 'Otto-Johannsen-Str.7 ';
这个东西的默认阈值是 0.3 ,可以使用 SET pg_trgm.similarity_threshold = 0.4 ; 进行更改。

3 索引优化
1 . GIN索引(推荐): sql 使用 GIN (address_string gin_trgm_ops) 在地址上创建索引 trgm_idx;
2 GIST索引(数据变化较大时使用): sql 使用 GIST (address_string gist_trgm_ops) 创建索引 trgm_idx_gist ON 地址;
索引对查询速度有很大影响。

4 完成示例问题
1 问题陈述: sql SELECT 地址字符串,相似度(地址字符串,'Otto-Johannsen-Str.7 ')AS result_similarity 发件人地址 WHERE 地址字符串 % 'Otto-Johannsen-Str.7 ' 按相似度结果 DESC 排序 LIMIT 1 0;
这将按相似度降序对项目进行排序,并获得前 1 0 个最相似的项目。

5 数据预处理
1 .删除干扰词: sql 创建或替换函数remove_noise_words(input_string TEXT,noise_words TEXT []) 返回文本为 $$ 声明 文本结果 := input_string; 噪声字文本; 我开始 FORnoise_words UP LOOPnoise_words 结果 := 替换(结果, word_noise, ''); 最后一个循环; 返回结果; 结尾; $$ LANGUAGE plpgsql;
SELECT remove_noise_words('Otto-Johannsen-Straße7 ', ARRAY['Straße', 'Str.']);
此函数可以删除无用的单词,例如“Str”。
和“酒店”。

2 标准化格式: sql -
替换缩写 -
使用大小写字母 SELECT LOWER(address_string) FROM 地址;
也可以使用PostGIS的ST_NormalizeAddress(),但必须先安装PostGIS。

6 注释
1 .阈值应调整: sql -
严格匹配:SET pg_trgm.similarity_threshold = 0.7 ; -
较差匹配:SET pg_trgm.similarity_threshold = 0.2 ;
如果数据质量好,则调高,如果数据质量差,则调低。

2 干扰词列表: 应将方向词(北、南)、单位词(建筑物、楼层)和一般词(The、And)添加到列表中。
数据定期更新。

3 性能监控: sql 解释分析 SELECT address_string FROM 地址 WHERE address_string % 'Otto-Johannsen-Str.7 ';
还有索引碎片的问题: sql REINDEX 索引 trgm_idx;
七、扩展应用
1 .不明确的名称匹配: sql SELECT 名称,相似度(名称,'JohannsenGmbH')结果 AS 来自公司 名称 % 'JohannsenGmbH' ORDER BY 结果 DESC;
2 .多列连接匹配: sql SELECT , 相似性(CONCAT(地址, 城市), 'Otto-Johannsen-Str.7 Berlin') AS 结果一般 出发地点 按总分 DESC 排序;
一般来说,如果pg_trgm用得好,大多数地址匹配问题都会得到解决。
关键是根据你的数据调整参数,多测试几次。