ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

组合查询、全文本搜索

2021-07-11 23:30:29  阅读:174  来源: 互联网

标签:UNION text 查询 note 搜索 WHERE 全文 SELECT


在这里插入图片描述
欢迎关注微信公众号:摸鱼汪的杂货铺

十七、组合查询

17.1 组合查询

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

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

17.2 创建组合查询

可用UNION操作符来组合数条SQL查询。利用UNION,可以给出多条SELECT语句,将他们的结果组合成单个结果集。

17.2.1 使用UNION

UNION的使用很简单。所需要做的只是给出每条SELECT语句,在各条语句之间放上关键字NUION。
举一个例子,假如需要价格小于5所有物品的一个列表,而且还想包括供应商1001和1002生产的所有物品(不考虑价格)。
我们先来看单挑SELECT语句的编写:

SELECT vend_id,prod_id,prod_price
FROM products
WHERE prod_price <= 5;

在这里插入图片描述

SELECT vend_id,prod_id,prod_price
FROM products
WHERE vend_id IN(1001,1002);

在这里插入图片描述

第一条SELECT检索价格不高于5的所有产品,第二条SELECT使用IN找出供应商为1001和1002的所有物品。组合这两条SELECT语句可以按如下进行:

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语句组成,语句中用UNION故拿剪子分隔。UNION只是MySQL执行两条SELECT语句,并把输出组合成单个查询结果集。
作为参考这里给出多条WHERE子句而不是使用UNION的相同查询:

SELECT vend_id,prod_id,prod_price
FROM products
WHERE vend_id IN (1001,1002)
OR prod_price <=5;

在这个简单的列子中使用UNION可能比使用WHERE子句更为复杂。但对于更复杂的过滤条件,或这从多个表(而不是单个表)中检索数据的情形,使用UNION可能会使处理更简单。

17.2.2 UNION规则

正如所见,并不是非常容易使用到的,但在进行并时有几条规则需要注意:
1.UNION必须由两条或两条以上的SELECT语句组成,语句之间用关键字UNION分隔(因此,如果组合4条SELECT语句,将要使用3个UNION关键字)。
2.UNION中的每个查询必须包含相同的列、表达式或聚集函数(不过各列不需要以相同的次序列出)。
3.列数据类型必须兼容:类型不必完全相同,但必须是DBMS可以隐含地转换的类型(例如,不同的数值类型或不同的日期类型)

17.2.3 包含或取消重复的行

请返回到17.2.1节认证查看所用样例,我们发现第一条SELECT语句返回4条,而第二条SELECT语句返回5行,但使用UNION组合语句的SELECT语句只返回8行而不是9行。
UNION从查询结果集中自动去除了重复的行(换句话说,它的行为与单条SELECT中使用多个WHERE子句条件一样)。因为供应商
生产的一种物品的介个也低于,所以两条SELECT语句都返回改行,在使用UNION时,重复的行被自动取消。
这是UNION默认的行为,但是如果需要,可以改变它,实际上如果想要返回所有匹配的行,可以使用UNION ALL而不是UNION,请看下面的例子:

SELECT vend_id,prod_id,prod_price
FROM products
WHERE prod_price <=5
UNION ALL
SELECT vend_id,prod_id,prod_price
FROM products
WHERE vend_id IN (1001,1002);

在这里插入图片描述

使用UNION ALL,MySQL不取消重复的行。因此这里的例子返回9行,其中一行出现两次。

17.2.4 对组合查询结果排序

SELECT语句的输出用ORDER BY子句排序。在用UNION组合查询时,只能使用一条ORDER BY子句。它必须出现在最后一条SELECT语句之后,对于结果集不存在用一种方式排序一部分,而又用另一种方式排序令一部分的情况,因此不允许使用多条ORDER BY子句。
用下面例子排序前面UNION返回的结果:

SELECT vend_id,prod_id,prod_price
FROM products
WHERE prod_price <=5
UNION ALL
SELECT vend_id,prod_id,prod_price
FROM products
WHERE vend_id IN (1001,1002)
ORDER BY vend_id,prod_price;

在这里插入图片描述

这条UNION在最后一条SELECT语句后使用了ORDER BY子句。虽然ORDER BY子句似乎是最后一条SELECT语句的组成部分,但实际上MySQL将用它来排序所有SELECT语句返回的结果。

十八、全文本搜索

18.1 理解全文本搜索

第八节介绍了LIKE关键字,他利用通配符匹配文本(和部分文本)。使用LIKE,能够查找包含特殊值或部分值的行(不管这些值位于列什么位置)。
在第九节中,用基于文本搜索作为正则表达式匹配列值的更进一步介绍。使用正则表达式,可以编写查找所需行的非常负载的匹配模式。
虽然这些搜索机制非常有用,但存在几个重要的限制:
1.性能——通配符和正则表达式匹配通常要求MySQL尝试匹配表中所有行(而且这些搜索极少使用表索引)。因此,由于被搜索行数不断增加,这些搜索可能非常耗时。
2.明确控制——使用通配符和正则表达式。很难(而且并不总是能)明确的控制匹配什么和不匹配什么。
3.智能化结果——虽然基于通配符和正则表达式的搜索提供了非常灵活的搜索,但他们都不能提供一种智能化的选择结果的方法。

18.2 使用全文本搜索

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

18.2.1 启用全文本搜索支持

一般在创建表时启用全文本搜索,CREATE TABLE语句接受FULLTEXT子句,他给出被索引列的一个逗号分隔的列表。下面的CREATE语句演示了FULLTEXT子句的使用:

CREATE TABLE productes(
	note_id INT 		NOT NULL AUTO_INCREMENT PRIMARY KEY,
	prod_id CHAR(10) 	NOT NULL,
	note_date DATETIME	NOT NULL,
	note_text TEXT		NULL FULLTEXT,
)

第二十一节会详细介绍CREATE TABLE语句,现在只需要知道用于创建数据库表就行。在这些列中note_text为了进行全文本搜索,MySQL根据子句FULLTEXT(note_text)的指示对它进行索引。这里的FULLTEXT索引单个列,如果需要也可以指定多个列。

18.2.2 进行全文本搜索

在索引之后,使用两个函数Match()和Against()执行全文本搜索,其中Match()指定被搜索的列,Against()指定要使用的搜索表达式。
下面举一个列子:

SELECT note_text
FROM productnotes
WHERE MATCH(note_text) AGAINST('rabbit')

在这里插入图片描述

此SELECT语句检索单个列note_text。由于WHERE子句,一个全文本搜索被执行。MATCH(note_text)指示MySQL针对指定的列进行搜索,AGAINST(‘rabbit’)指定词rabbit作为搜索文本。由于有两行包含词rabbit,这两个行被返回。

事实上这个例子也可以用简单的LIKE子句完成,如下面所示:

SELECT note_text
FROM productnotes
WHERE note_text LIKE '%rabbit%';

在这里插入图片描述

这条SELECT语句同样检索出两行,但次序不同(虽然并不总是出现这种情况)。

上述几条SELECT语句都不包含ORDER BY子句。后者(使用LIKE)以不特别有用的顺序返回数据。前者(使用全文本搜索)返回以文本匹配的良好程度排序的顺序。这两个行都包含词rabbit,但包含词rabbit作为第3个词的行等级比作为第20个词的行高。这很重要。全文本搜索的一个重要部分就是对结果排序。具有较高等级的行先返回(因为这些行很可能是你真正想要的行)。

为演示排序如何工作请看下面的例子:

SELECT note_text,
MATCH(note_text) AGAINST('rabbit') AS rank
FROM productnotes;

在这里插入图片描述

在这里插入图片描述

这里,在SELECT而不是WHERE子句中使用MATCH()和AGAINST()。这使所有行都被返回(因为没有WHERE子句)。MATCH()和AGAINST()用来建立一个计算列(别名为RANK),此列包含全文本搜索计算出的等级值。等级由MySQL根据行中词的数目、唯一词的数目、整个索引中词的总数以及包含该词的行的数目计算出来。正如所见,不包含词rabbit的行等级为0(因此不被前一个例子中的WHERE子句选择)。确实包含词rabbit的两个行每行都有一个等级值,文本中词靠前的行的等级比词靠后的行的等级值高。

这个例子有助于说明全文本搜索如何排除行(排除那些等级为0的行),如何排序结果(按等级以降序排序)。

18.2.3 使用扩展查询

查询扩展用来设法放宽所返回全文本搜索结果的范围。考虑下面的情况。你想找出所有提到anvils的注释。只有一个注释包含词anvils,但你还想找出可能与你搜索有关的所有其他行,即使它们不包含词anvils。
这也是查询扩展的一项任务。在使用查询扩展时,MySQL对数据和索引进项两遍扫描来完成搜索。
1.首先,进行一个基本的全文本搜索,找出于搜索体哦阿健匹配的所有行。
2.其次,MySQL检查这个匹配行并选择所有有用的词(我们将会简要的解释MySQL如何断定什么有用,什么没用)
3.再其次,MySQL再次进行全文本搜索,这次不仅使用原来的条件,而且还使用所有有用的词。
利用查询扩展,能找到可能相关的结果,即使它们并不精确包含所查找的词。

扩展查询功能只应用于MySQL4.1.1或更高级的版本

下面举一个例子,首先进行一个简单的全文本搜索,没有查询扩展:

SELECT note_text
FROM productnotes
WHERE MATCH(note_text) AGAINST('anvils');

在这里插入图片描述

只有一行包含词anvils,因此只返回一行

下面是相同的搜索,这次使用查询扩展:

SELECT note_text
FROM productnotes
WHERE MATCH(note_text) AGAINST('anvils' WITH QUERY EXPANSION);

在这里插入图片描述

这次返回了7行。第一行包含词anvils,因此等级最高。第二行与anvils无关,但因为它包含第一行中的两个词(customer和recommend),所以也被检索出来。第三行也包含这两个相同的词,但它们在文本中的位置更靠后且分开的更远,因此在这一行,但等级为第三行。第三行确实也没有设计anvils。

正如所见,查询扩展极大地增加了返回地行数,但这样也增加了你实际上并不想要地行地数目。

18.2.4 布尔文本搜索

MySQL支持全文本搜索地另外一种形式,称为布尔方式(boolean mode)。以布尔方式,可以提供关于如下内容地细节:
1.要匹配的词;
2.要排斥的词(如果某行包含这个词,则不会返回改行,即使它包含其他指定的词也是如此);
3.排列提示(指定某些词比其他词更重要,更重要的此等级更高);
4.表达式分组;
5.另外一些内容。

为演示IN BOOLEAN MODE的作用,举一个简单的例子:

SELECT note_text
FROM productnotes
WHERE MATCH(note_text) AGAINST('heavy' IN BOOLEAN MODE);

此全文本搜索检索包含heavy的所有行(有两行)。其中使用了关键字IN BOOLEAN MODE,但实际上没有指定布尔操作符,因此,其结果与没有指定布尔方式结果相同。

为了匹配包含heavy但不包含rope开始的词的行,可使用以下查询:

SELECT note_text
FROM productnotes
WHERE MATCH(note_text) AGAINST('heavy -rope*' IN BOOLEAN MODE);

这次只返回一行。这次仍然匹配词heavy,但-rope*明确地指示MySQL排除包含rope *(任何以rope开始的词,包括ropes)的行,这就是为什么返回上一个例子中的第一行被排除的原因。

全文本布尔操作符列出支持的所有布尔操作符。
在这里插入图片描述

下面举几个例子,说明某些操作符如何使用:

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而不是匹配两个词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和combinnation,降低后者的等级

18.2.5 全文本搜索的使用说明

1.在索引全文本数据时,短词被忽略且从索引中排除。短词定义为那些具有3个或3个以下字符的词(如果需要,这个数目可以更改)
2.MySQL带有一个内建的非用词(stopword)列表,这些词在索引全文本数据时总是被忽略。如果需要,可以覆盖这个列表
3.许多词出现的频率很高,搜索它们没有用处(返回太多结果)。因此,MySQL规定了一条50%规则不用于IN BOOLEAN MODE。
4.如果表中的行数少于3行,则全文本搜索不反悔结果(因为每个词或者不出现,或者至少出现在50%的行中)。
5.忽略词中的单引号。例如don’t索引为dont。

18.2.5 全文本搜索的使用说明

1.在索引全文本数据时,短词被忽略且从索引中排除。短词定义为那些具有3个或3个以下字符的词(如果需要,这个数目可以更改)
2.MySQL带有一个内建的非用词(stopword)列表,这些词在索引全文本数据时总是被忽略。如果需要,可以覆盖这个列表
3.许多词出现的频率很高,搜索它们没有用处(返回太多结果)。因此,MySQL规定了一条50%规则不用于IN BOOLEAN MODE。
4.如果表中的行数少于3行,则全文本搜索不反悔结果(因为每个词或者不出现,或者至少出现在50%的行中)。
5.忽略词中的单引号。例如don’t索引为dont。
6.不具有此分隔符(包括日期和汉语)的语言不能恰当的返回全文本搜索结果。

标签:UNION,text,查询,note,搜索,WHERE,全文,SELECT
来源: https://blog.csdn.net/m0_46363470/article/details/118662015

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有