前言
这文主要介绍MySQL查询,联结表,全文索引的常用语句
使用子查询
使用IN操作符进行子查询
1 | select cust_id from orders where order_num in (select order_num from orderitems where prod_id = 'TNT2') |
作为计算字段使用子查询
1 | select cust_name,cust_state,(select count(*) from orders where orders_cust_id = customers.cust_id) as orders from customers order by cust_name; |
联结表
联结
当数据存储在多个表时,表之间还存在外键关系,这时如果要检索出牵连多个表的数据时,使用联结来解决。
下图是常见的联结方式(主要是JOIN操作):
使用WHERE子句创建联结
为了避免出现二义性,必须使用完全限定名,即用一个点分隔的表名和列名。1
2
3//两个表之间用where进行联结,指示MySQL匹配vendors表中的vend_id和products表中vent_id
select vend_name,prod_name,prod_price from vendors,products where vendors.vend_id = products.vent_id
笛卡尔积
由没有联结条件的表关系返回的结果为笛卡尔积。即检索出的行的数目将是第一个表中的行数乘以第二个表中的行数
内部联结(也称等值联结)
使用 INNER JOIN…ON
使用INNER JOIN指定表,ON指出联结条件,与WHERER条件效果一样。使用明确的联结语法能够确保不会忘记联结条件。
1 | //以inner join..on的形式代替where |
性能考虑
MySQL在运行时关联指定每个表以处理联结,这种处理是非常消耗资源的,应当避免联结过多的表,不必要的表
外部联结
联结包含了那些在相关表中没有关联的行,这种类型的联结称为外部联结
左外联结和右外联结(LEFT/RIGHT OUTER JOIN ..ON)
外部联结包含没有关联的行,在使用OUTER JOIN必须使用RIGHT或者LEFT关键字指定包括其所有行的表(RIGHT指出的是OUTER JOIN右边的表,LEFT指出的是LEFT JOIN左边的表)
1 | //从右边的表选出所有行,左边的表没有匹配的话,默认为空 |
我们实际使用过程中,一般使用内部联结,但是用外部联结也是有效的
组合查询
使用UNION
使用UNION很简单,只需要在每条SELECT语句之间加上UNION就可以了,效果与WHERE效果一样
1 | select vend_id,prod_id,prod_price from products where prod_price <= 5 |
等价于使用where语句1
select vend_id,prod_id,prod_price from products where prod_price <= 5 or vend_id in (1001,1002)
虽然看似UNION子句更复杂,但是在有更复杂的过滤条件时,使用UNION可能会显得更方便
UNION的规则
- UNION必须由两条或两条以上的SELECT语句组成
- UNION中的每个查询必须包含相同的列,表达式或聚集函数
- 列数据类型必须兼容
包含或取消重复的行
UNION从查询结果集中自动去除了重复的行,如果需要,可以用UNION ALL匹配所有的行
对组合查询结果排序
在UNION组合查询时,只能使用一条ORDER BY语句,它必须出现在最后一条SELECT语句之后。当然,这个排序是对前面所有SELECT语句都起作用的
全文本搜索
从MySQL5.6版开始支持InnoDB引擎的全文索引,在5.6之前主要是MyISAM引擎支持全文索引。
MySQL支持三种全文索引模式:
- 自然语言模式,即用MATCH AGAINST执行全文本搜索
- 布尔模式。可以为检索的字符串增加操作符,例如“+”表示必须包含,“-”表示不包含,“*”表示通配符
- 查询扩展模式。会执行两次检索,第一次使用给定的短语进行检索,第二次是结合第一次相关性比较高的行进行检索。
目前MySQL支持在CHAR,VARCHAR,TEXT类型的列上定义全文索引
创建全文索引
1 | mysql> create table test( |
1 | mysql> select text from test where match(text) against('users'); |
两个函数Match()和Against()必须和where子句配合使用
布尔模式
未使用布尔模式,检索包含MySQL字段的,有两条1
2
3
4
5mysql> select text from test where match(text) against('MySQL');
| text|
| This manual describes features that are not included in every edition of MySQL 5.7; such features may not be included in the edition of MySQL 5.7 licensed to you. If you have any questions about the features included in your edition of MySQL 5.7, refer to your MySQL 5.7 license agreement or contact your Oracle sales representative. |
| For help with using MySQL, please visit either the MySQL Forums or MySQL Mailing Lists, where you can discuss your issues with other MySQL users. |
2 rows in set (0.08 sec)
使用布尔模式, -users*表示去除有users*的行,这里的*是通配符,表示任何以users开头的词1
2
3
4
5mysql> select text from test where match(text) against('MySQL -users*' in boolean mode);
| text|
| This manual describes features that are not included in every edition of MySQL 5.7; such features may not be included in the edition of MySQL 5.7 licensed to you. If you have any questions about the features included in your edition of MySQL 5.7, refer to your MySQL 5.7 license agreement or contact your Oracle sales representative. |
1 row in set (0.08 sec)