第十七章 组合查询
在 MySQL 中,可以执行多条查询语句,然后对多个结果集,使用UNION语句合并成单个查询结果集返回。主要有以下两种应用场景: 1.在单个查询中从不同的表返回类似结构的数据。 2.对单个表执行多个查询,将结果集合并成一个结果集。
使用UNION
例如我们需要价格小于等于5的所有物品的一个列表,而且 还想包括供应商1001和1002生产的所有物品(不考虑价格),
这条语句由前面的两条SELECT语句组成,语句中用UNION关键 字分隔。UNION指示MySQL执行两条SELECT语句,并把输出组 合成单个查询结果集,当然这个需求也可以使用多条WHERE语句来实现。
注意事项:
1.UNION必须由两条或两条以上的SELECT语句组成,语句之间用关 键字UNION分隔(因此,如果组合4条SELECT语句,将要使用3个 UNION关键字)。
2.UNION中的每个查询必须包含相同的列、表达式或聚集函数(不过 3.列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以 隐含地转换的类型(例如,不同的数值类型或不同的日期类型)。 如果遵守了这些基本规则或限制,则可以将并用于任何数据检索任务。
4.在用UNION组合查询时,如果需要对结果进行排序,只能使用一条ORDER BY子句,它必须出现在最后一条SELECT语句之后。对 于结果集,不存在用一种方式排序一部分,而又用另一种方式排序另一 部分的情况,因此不允许使用多条ORDER BY子句。
5.UNION从查询结果集中自动去除了重复的行(换句话说,它的行为与 单条SELECT语句中使用多个WHERE子句条件一样)。因为供应商1002生产 的一种物品的价格也低于5,所以两条SELECT语句都返回该行。在使用 UNION时,重复的行被自动取消。这是UNION的默认行为,但是如果允许重复,可以使用UNION ALL而不是UNION。如下图所示:
第十八章 组合查询
当我们需要对文本进行匹配,可以使用LIKE+通配符,或正则表达式的方式来实现,但是这样会存在很多限制:
1.性能不高——通配符和正则表达式匹配通常要求MySQL尝试匹配表中所有行(而且这些搜索极少使用表索引)。因此,由于被搜索行数不断增加,这些搜索可能非常耗时。
2.不太灵活——使用通配符和正则表达式匹配,很难(而且并不总是能)明确地控制匹配什么和不匹配什么。例如,指定一个词必须匹配,一个词必须不匹配,而一个词仅在第一个词确实匹配的情况下才可以匹配或者才可以不匹配。
3.无法智能化——虽然基于通配符和正则表达式的搜索提供了非常灵活的搜索,但它们都不能提供一种智能化的选择结果的方法。 例如,一个特殊词的搜索将会返回包含该词的所有行,而不区分包含单个匹配的行和包含多个匹配的行(按照可能是更好的匹配 来排列它们)。类似,一个特殊词的搜索将不会找出不包含该词但包含其他相关词的行。所以就有了全文搜索,为了进行全文本搜索,必须索引被搜索的列,而且要随着数据的改 变不断地重新索引。在对表列进行适当设计后,MySQL会自动进行所有 的索引和重新索引。在索引之后,SELECT可与Match()和Against()一起使用以实际执行 搜索。
启用全文本搜索支持
在建表时或者建表以后使用FULLTEXT语句指定全文搜索的列,MySQL根据子句FULLTEXT(note_text)的指示对它进行索引,在之后该列增加、更新或删除行时, 索引随之自动更新 如下图所示:
注意事项:
如果正在导入数据到一个新表, 此时不应该启用FULLTEXT索引。应该首先导入所有数据,然后再修改表,定义FULLTEXT,这样花费的时间会更少。
进行全文本搜索
在索引之后,使用两个函数Match()和Against()执行全文本搜索, Match() 指定被搜索的列 Against() 指定要使用的搜索表达式 如下图所示:SELECT语句检索单个列note_text,将包含rabbit的行进行返回。(全文搜索默认不区分大小写,除非使用BINARY语句进行修饰)
全文搜索还可以使用Rank对结果进行排序,Match()和Against() 用来建立一个计算列(别名为rank),此列包含全文本搜索计算出的等级 值。等级由MySQL根据行中词的数目、唯一词的数目、整个索引中词的 总数以及包含该词的行的数目计算出来。不包含搜索词的行等级为0(因此不被前一例子中的WHERE子句选择)。确实包含搜索词的两个行每行都有一个等级值,文本中词靠前的行的等级值比词靠后的行的等级值高。如下图所示:
如果指定多个搜索项,则包含多数匹配词的 那些行将具有比包含较少词(或仅有一个匹配)的那些行高的 等级值。
使用查询扩展
查询扩展用来设法放宽所返回的全文本搜索结果的范围,它可以先进行一个基本的全文本搜索,找出与搜索条件匹配的所有行。其次,MySQL检查这些匹配行并选择所有有用的词,再其次,MySQL再次进行全文本搜索,这次不仅使用原来的条件, 而且还使用所有有用的词。如下图所示;
布尔文本搜索
MySQL支持全文本搜索的另外一种形式,称为布尔方式(boolean mode)。可以指定要匹配的词,要排斥的词,排列提示(指定某些词比其他词更重要,更重要的词等级更高),表达式分组等。即使没有定义 FULLTEXT索引,也可以使用它。但这是一种非常缓慢的操作。 例如: 在下图里面的查询中,会匹配词heavy,但-rope明确地 分析指示MySQL排除包含rope(任何以rope开始的词,包括 ropes)的行。
除了布尔操作符-和,-排除一个词,而 是截断操作符(可想象为用于词尾的一个通配符)。还有以下全文本布尔操作符:
下面是一些全文本布尔操作符使用案例:
全文本搜索的使用说明
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全文本搜索现在还不支持邻近操作符。