《MySQL必知必会》学习笔记九(组合查询&全文本搜索)------掌握部分

时间:2022-09-16 10:48:44

MySQL必知必会知识预览
第一章——了解SQL
第二章——MySQL简介
第三章——使用MySQL
第四章——检索数据
第五章——排序检索数据
第六章——过滤数据
第七章——数据过滤
第八章——用通配符进行过滤
第九章——用正则表达式进行搜索
第十章——创建计算字段
第十一章——使用数据处理函数
第十二章——汇总数据
第十三章——分组数据
第十四章——使用子查询
第十五章——联结表
第十六章——创建高级联结
第十七章——组合查询
第十八章——全文本搜索
第十九章——插入数据
第二十章——更新和删除数据
第二十一章——创建和操纵表
第二十二章——使用视图
第二十三章——使用储存过程
第二十四章——使用游标
第二十五章——使用触发器
第二十六章——管理事务处理
第二十七章——全球化和本地化
第二十八章——安全管理
第二十九章——数据库维护
第三十章——改善性能
————————————– 华丽的分隔符 ————————————————–

第十七章union

利用union操作符将多条select 语句组合成一个结果集。
复合查询
多数SQL查询都只包含从一个或多个表中返回数据的单条select语句。MySQL也是允许执行多个查询(多条select语句),并将结果作为单个查询结果集返回。这些组合查询称为并(union)或者复合查询。

两种基本情况使用组合查询
1. 在单个查询中从不同的表中返回类似结构的数据
2. 在对单个表执行多个查询,按照单个查询返回数据

组合查询和多个where条件
多数情况下,组合相同表的两个查询完成的工作与具有多个where子句条件的单条查询完成的工作相同。也就是说,任何具有多个where子句的select语句都可以作为一个组合查询给出。这两种技术在不同的查询中宁性能也是不同,因此,应该试一下这种技术,然后选择性能更好的查询。

使用union只是在各条语句之间放上关键字union

select vend_id,prod_id,prod_price from products where prod_price <=5 union select vend_id,prod_id,prod_price from products where vend_id in(1001,1002);

select vend_id,prod_id,prod_price from products where vend_id in
(1001,1002) union select vend_id,prod_id,prod_price from products where
prod_price <=5; // 无关先后顺序
《MySQL必知必会》学习笔记九(组合查询&全文本搜索)------掌握部分

union从查询结果中会自动删除重复行,where也是会自动去除重复行
union All 则不会从结果中自动删除重复行。

组合查询使用规则:
1.必须由两条或者两条以上的select语句组成,语句之间用关键字union分隔
2.每个查询中必须包含相同的列,表达式或聚集函数(顺序可以不同)
3.列数据类型必须兼容,类型不必完全相同,但必须是DBMS可以隐含地转换的类型。

对组合查询结果的排序
Select 语句的输出用order by子句排序,在用union查询时,只能在最后一条select子句之后使用order by不允许使用多条order by 子句

select vend_id,prod_id,prod_price from products where vend_id in
(1001,1002) union select vend_id,prod_id,prod_price from products where
prod_price <=5 order by vend_id,prod_price;
《MySQL必知必会》学习笔记九(组合查询&全文本搜索)------掌握部分

注意:组合查询可以组合不同的表之间的查询,但是要保证查询的返回的列,表达式,或者聚合函数保持一致。

第十八章FULLTEXT&Match()&Against()

全文本搜索:
并非所有的引擎都支持全文本搜索,两个最常用的引擎为MyISAM 和 InnocenceDB,前者支持全文本搜索后者不支持。如果应用中需要使用全文搜索功能,则应该记住使用MYISAM引擎

全文本搜索&LIKE关键字搜索&正则表达式搜索

使用like关键字或者是利用正则表达式进行搜索,这些搜索机制非常有用,但是存在几个限制:
1.性能—— 通配符和正则表达式匹配通常要求MySQL尝试匹配表中所有行(而且这些搜索极少使用表索引)。因此,由于被搜索行数不断增加,这些搜索可能非常耗时。
2.明确控制——-使用通配符和正则表达式匹配,很难(而且不总是能)明确地控制匹配什么和不匹配什么
3.智能化的结果——-虽然基于通配符和正则表达式的搜索提供了非常灵活的搜索,但他们都不能提供一种智能化的选择结果的方法。

所有这些限制,以及更多的限制都可以使用全文本搜索来解决。在使用全文本搜索时,MySQL不需要分别查看每个行,不需要分别分析和处理每个词。MySQL创建指定列中各词的一个索引,索引可以根据针对这些词进行。这样,MySQL可以快速有效的决定那些词匹配(那些行包含他们),哪些词不匹配,它们匹配的频率,等等

使用全文本搜索

使用全文本搜索,必须索引被搜索的列,而且要随着数据的改变不断地重新索引。在对表进行适当的设计后,MySQL会自动进行所有的索引和重新索引。在索引之后,select可与Match()Against()一起使用以实际执行搜索。

  • 定义全文本

一般是在创建表时启动全文本搜索。Create Table语句接受 FULL text子句,她给出被索引列的一个逗号分隔列表。

mysql> CREATE table productnote(
note_id int not null auto_increment,
prod_id char(10) not null,
note_date datetime not null,
note_text text null,
PRIMARY KEY(note_id),
FULLTEXT(note_text)
) engine=MyISAM;

// MySQL根据子句FULLTEXT(note_text)的指示对它进行索引,如果索引多个列,逗号隔开,在定义之后,MySQL自动维护该索引,在增加,更新或者删除行时,索引随之自动更新。

注意:
FuLLText 索引关键字一般在创建表时指定FullText,或者在稍后指定(在这种情况下所有已有数据必须立即索引)
不要在导入数据时使用 fulltext, 更新索引要花时间,虽然不是很多,但毕竟要花时间,如果正在导入数据到一个新表,此时不应该启用fulltext索引,应该首先导入所有数据,然后在修改表,定义fulltext。这样有助于更快地导入数据(而且使索引数据的总时间小于在导入每行时分别进行索引所需要的总时间)

  • 使用全文本搜索

select note_text from productnotes where Match(note_text) against(‘rabbit’)

《MySQL必知必会》学习笔记九(组合查询&全文本搜索)------掌握部分

注意:
1、使用完整的Match() 传递Match()的值必须与FULLTEXT()定义中的相同。如果指定多个列,则是必须列出它们(而且次序正确)。Against()传递所要检索的内容
2、使用索引进行全文搜索,返回以文本匹配的良好程度排序的数据。两行都包含词robbit,但是包含词rabbit作为第三个词的行的等级比作为第二十个词的行高,这很重要全文搜索的一个重要的部分就是对结果排序。具有较高等级的行先返回。而利用like则不具备这种排序效果。
3、搜索不区分大小写,除非使用关键字Binary。

使用like子句完成相同工作(图片对比):
select note_text from productnotes where note_text like ‘%rabbit%’;
《MySQL必知必会》学习笔记九(组合查询&全文本搜索)------掌握部分

  • 演示排序如何工作:
    select note_text,MAtch(‘note_text’) against(‘rabbit’) as rank from productnotes;
    《MySQL必知必会》学习笔记九(组合查询&全文本搜索)------掌握部分

解释:
在select而不是where子句中使用Match()和Against()。这使所有航都被返回(因为灭有where子句)。Match()和Against()用来建立一个计算列,此列包含全文本搜索计算出的等级值。等级由MySQL根据行中词的数目、唯一词的数目、整个索引中词的总数以及包含该词的行的数目计算出来。正是这样,不包含rabbit的行等级为0(这个原因导致不被前一例子中的where子句所选择)。确实包含词rabbit的两个行每行都有一个等级值,文本中词靠前的行的等级值比词靠后的行的等级值高。
总结
说明了全文本搜索时如何排除行(排除那些等级为0的行),如何排序结果(按等级以降序排序)。如果指定多个搜索项,则是包含多数匹配词的那些行将具有比包含较少词(或仅有一个匹配)的那些行高的等级值。全文本搜索提供了简单的LIKE搜搜不能提供的功能。而且,由于数据是索引的,在数据比较大的时候,全文本搜索还是相当快的。

使用扩展查询 with query expansion

在使用扩展查询时,MySQL对数据和索引进行两遍扫描来完成搜索。
首先,进行一个基本的全文本搜索,找出与搜索条件匹配的所有行;
其次,MySQL检查这些匹配行并选择所有有用的词
然后MySQL再次进行全文本搜索,这次不仅使用原来的条件,而且还是用所有有用的词。

扩展查询在MySQL4.1.1中引入。

利用扩展查询,能找出可能相关的结果,即使他们并不精确包含所查找的词。
(有没有感觉很类似百度搜索)
select note_text from productnotes where Match(note_text) against (‘anvils’);
select note_text from productnotes where Match(note_text) against (‘anvils’ with query expansion);
《MySQL必知必会》学习笔记九(组合查询&全文本搜索)------掌握部分

解释:返回七行,第一行包含anvils,因此等级最高,第二行与anvils无关,但是因为它包含第一行中的两个词(customer 和 recommend) ,所以也被检索出来,第三行也包含这两个相同的词,但他们在文本中的位置更靠后且分开得更远。因此也包含,且等级为第三,第三行确实没有涉及anvils(按他们的产品名)

查询扩展极大的增加了返回的行数,但这样也增加了你实际不想要的行的数目。

布尔文本搜索

以布尔方式。可以提供关于如下内容的细节:
1.要匹配的词;
2.要排斥的词(如果某行包含这个词,则不返回改行,即使包含其他指定的词,也被排斥掉);
3.排列提示(指定某些词比其他词更重要,更重要的词等级更高);
4.表达式分组;
5.另外一些内容;

注意:布尔方式不同于迄今为止使用的全文本搜索语法的地方在于,即使没有定义fulltext索引,也是可以使用的,但这是一种非常缓慢的操作(性能会随数据量的增加而降低)。

select note_text from productnotes where Match(note_text) against(‘heavy’
in boolean mode);
// 注意 此全文本搜索检索包含heavy的所有行,其中使用了关键字 IN BOOLEAN MODE ,但是实际上没有指定布尔操作符,因此,此结果与没有指定布尔方式的结果相同。。考虑为什么?
《MySQL必知必会》学习笔记九(组合查询&全文本搜索)------掌握部分

select note_text from productnotes where Match(note_text) against('heavy-rope*' in boolean mode);  
// 匹配heavy 但排除任何以rope开始的词。

select note_text from productnotes where Match(note_text) against('+rabbit +bait' in boolean mode);
//匹配 包含词rabbit 和 bait 的行

select note_text from productnotes where Match(note_text) against('rabbit bait' in boolean mode);
// 匹配 包含词rabbit 或bait 的行[至少有一个]

select note_text from productnotes where Match(note_text) against( '“rabbit bait” ' in boolean mode);
//匹配短语rabbit bait 的行 **注意引号区别于上**

select note_text from productnotes where Match(note_text) against('>rabbit <carrot' in boolean mode);
//匹配rabbit 和carrot, 增加前者的等级,降低后者的等级

select note_text from productnotes where Match(note_text) against('+safe+(<combination)' in boolean mode);
// 匹配safe和combination,降低后者的等级。

排序而不排列,在布尔方式中,不按照等级值降序排序返回行。

全文本搜索的使用说明(重点)
1. 在搜索全文本数据时,短词被忽略且从索引中排除。短词定义为那些具有3个或3个一下字符的词(如果需要,数目可以更改)。
2. MySQL带有一个内建的非用词(stopword)列表,这些词在索引全文本数据时总是被忽略,如果需要,可以覆盖这个列表(参考MySQL文档)。
3. 许多词出现的频率很高,搜索他们没有用处,因此MySQL规定了一条50%规则,如果一个词出现在50%以上的行中,则将它作为一个非用词忽略。50%规则不使用in boolean mode。
4. 如果表中的行数少于3行,则全文本搜索不返回结果,(因为每个词或者不出现,或者至少出现在50%的行中)。
5. 忽略词中的单引号。Don’t 索引为dont。
6. 不具有词分隔符(包括日语和汉语)的语言不能恰当地返回全文本搜索结果。
7. 仅在MYISAM数据库引擎中支持全文本搜索。
8. 没有邻近操作符 邻近搜索时许多文本搜索支持的一个特性。他能搜索相邻的词。但是MySQL全文本搜索现在暂时不支持邻近操作符。