前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除
一、基本查询语句
MySQL从数据表中查询数据的基本语句为SELECT语句。其基本格式为:
sql
select
{* | <字段列表>}
[
from <表1>,<表2>...
[where <表达式>
[group by <group by definition>]
[having <expression> [{<operator> <expression>}...]]
[order by <order by definition>]
[limit [<offset>,] <row count>]
]
select [字段1,字段2,...,字段n]
from [表或视图]
where [查询条件];
其中,各条子句的含义如下:
- {* | <字段列表>}包含星号通配符和字段列表,表示查询的字段。其中,字段列表至少包含一个字段名称,如果要查询多个字段,多个字段之间用逗号隔开,最后一个字段后不加逗号
- FROM<表 1>,<表 2>...,表1和表2表示查询数据的来源,可以是单个或者多个。
- WHERE子句是可选项,如果选择该项,将限定查询行必须满足的查询条件
- GROUP BY <字段>,该子句告诉MySQL如何显示查询出来的数据,并按照指定的字段分组
- [ORDER BY<字段>],该子句告诉MySQL按什么样的顺序显示查询出来的数据,可以进行的排序有升序(ASC),降序(DESC)
- [LIMIT [<offset>,]<row count>],该子句告诉MySQL每次显示查询出来的数据条数
首先定义一个数据表并插入数据:
sql
create table fruits(
f_id char(10) not null,
s_id int not null,
f_name char(255) not null,
f_price decimal(8,2) not null,
primary key(f_id)
);
insert into fruits (f_id,s_id,f_name,f_price) values('a1',101,'apple',5.2),('b1',101,'blackberry',10.2),('bs1',102,'orange',11.2),('bs2',105,'melon',8.2),('t1',102,'banana', 10.3),('t2',102,'grape',5.3),('2',103,'coconut',9.2),('c0',101,'cherry',3.2),('a2',103,'apricot',2.2),('12',104,'lemon',6.4),('b2',104,'berry',7.6),('m1',106,'mango',15.7),('m2',105,'xbabay',2.6),('t4',107,'xbababa',3.6),('m3',105,'xxtt',11.6),('b5',107,'xxxx',3.6);
使用select语句查询f_id字段的数据:
sql
select f_id,f_name from fruits;
二、单表查询
1、查询所有字段
(1)在select语句中使用星号(*)通配符查询所有字段
sql
select * from 表名;
# 示例:从fruits表中检索所有字段的数据
select * from fruits;
...
可以看到,使用星号(*)通配符时,将返回所有列,列按照定义表时候的顺序显示
(2)在select语句中指定所有字段
sql
select f_id,s_id,f_name,f_price from fruits;
2、查询指定字段
(1)查询单个字段
sql
select 列名 from 表名;
# 示例:查询fruits表中f_name列所有的水果名称
select f_name from fruits;
(2)查询多个字段
sql
select 字段1,字段2,...字段n from 表名;
# 示例:从fruits表中获取f_name和f_price两列
select f_name,f_price from fruits
3、查询指定记录
在select语句中,通过where子句对数据进行过滤:
sql
select 字段1,字段2,...,字段n
from 表名
where 查询条件
在WHERE 子句中,MySOL提供了一系列的条件判断符,查询结果如下:
操作符 | 说明 |
---|---|
= | 相等 |
<>,!= | 不相等 |
< | 小于 |
<= | 小于等于 |
> | 大于 |
>= | 大于等于 |
between | 位于两值之间 |
sql
# 示例:查询价格为10.2元的水果的名称
select f_name,f_price from fruits where f_price = 10.2
# 相等还可以用来比较字符串
# 示例:查找名称为'apple'的水果的价格
select f_name,f_price from fruits where f_name = 'apple';
# 示例:查询价格小于10的水果的名称:
select f_name,f_price from fruits where f_price < 10;
4、带IN关键字查询
IN操作符用来查询满足指定范围内的条件的记录,使用IN操作符,将所有检索条件用括号括起来,检索条件之间用逗号分隔开,只要满足条件范围内的一个值即为匹配项。
sql
# 示例:查询s_id为101和102的记录:
select s_id,f_name,f_price
from fruits
where s_id in (101,102)
order by f_name;
相反,可以使用关键字NOT来检索不在条件范围内的记录:
sql
# 示例:查询所有s_id不等于101也不等于102的记录
select s_id,f_name,f_price
from fruits
where s_id not in (101,102)
order by f_name;
5、带BETWEEN AND的范围查询
BETWEEN AND用来查询某个范围内的值,该操作符需要两个参数,即范围的开始值和结束值,如果字段值满足指定的范围查询条件,则这些记录被返回。
sql
# 示例:查询价格在2.00元到10.20元之间的水果名称和价格
select f_name,f_price from fruits where f_price between 2.00 and 10.20;
BETWEEN AND操作符前可以加关键字NOT,表示指定范围之外的值,如果字段值不满足指定的范围内的值,则这些记录被返回。
sql
# 示例:查询价格在2.00元到10.20元之外的水果名称和价格
select f_name,f_price
from fruits
where f_price not between 2.00 and 10.20;
6、带LIKE的字符匹配查询
通配符是一种在SQL的WHERE条件子句中拥有特殊意思的字符。SQL语句中支持多种通配符,可以和 LIKE一起使用的通配符有'%'和'_';
(1)百分号通配符'%',匹配任意长度的字符,甚至包括零字符
sql
# 示例:查找所有以'b'字母开头的水果
select f_id,f_name
from fruits
where f_name like 'b%';
在搜索匹配时通配符'%'可以放在不同位置;
sql
# 示例:查找f_name中包含字母'g'的记录
select f_id,f_name
from fruits
where f_name like '%g%';
# 查询以'b'开头并以'y'结尾的水果的名称
select f_name
from fruits
where f_name like 'b%y';
(2)下划线通配符,一次只能匹配任意一个字符
sql
# 示例:查询以字母'y'结尾,其'y'前面只有4个字母的记录
select f_id,f_name from fruits where f_name like '____y';
7、查询空值
数据表创建的时候,设计者可指定某列中是否包含空值(NULL) 。空值不同于0,也不同于空字符串。空值一般表示数据未知、不适用或将在以后添加数据。在SELECT语句中使用ISNULL子句,可以查询某字段内容为空记录
sql
# 示例:创建数据表customers,该表包含本示例需要的数据
create table customers(
c_id int not null auto_increment,
c_name char(50) not null,
c_address char(50) null,
c_city char(50) null,
c_zip char(10) null,
c_contact char(50) null,
c_email char(255) null,
primary key (c_id)
);
insert into customers (c_id,c_name,c_address,c_city,c_zip,c_contact,c_email) VALUES(10001,'RedHook','200 Street','Tianjin','300000','LiMing','LMing@163.com'),(10002,'Stars','333 Fromage Lane','Dalian','116000','Zhangbo','Jerry@hotmail.com'),(10003,'Netbhood','1 Sunny Place','Qingdao','266000','LuoCong',NULL),(10004,'J0TO','829 Riverside Drive','Haikou','570000','YangShan','sam@hotmail.com');
# 查询customers表中c_email为空的记录c_id、c_name和c_email字段值
select c_id,c_name,c_email from customers where c_email is null;
与IS NULL相反的是NOT NULL ,该关键字查找字段不为空的记录
sql
# 示例:查询customers表中c_email不为空的记录的c_id、c_name和c_email字段值
select c_id,c_name,c_email from customers where c_email is not null;
8、带AND的多条件查询
使用SELECT查询时,可以增加查询的限制条件,这样可以使查询的结果更加精确。MySQL在WHERE 子句中使用AND操作符限定只有满足所有查询条件的记录才会被返回。可以使用AND连接两个甚至多个查询条件,多个条件表达式之间用AND分开;
sql
# 示例:在fruits表中查询s_id=101并且f_price大于等于5的水果id、价格和名称
select f_id,f_price,f_name from fruits where s_id='101' and f_price >=5;
# 在fruits表中查询sid=101或者102,并且fprice大于等于5、fname='apple'的水果价格和名称
select f_id,f_price,f_name from fruits
where s_id in('101','102') and f_price >= 5 and f_name = 'apple';
9、带OR的多条件查询
与AND相反,在 WHERE声明中使用 OR操作符,表示只需要满足其中一个条件的记录即可返回。OR也可以连接两个甚至多个查询条件,多个条件表达式之间用OR分开
sql
# 示例:查询s_id=101或者s_id=102的水果供应商的f_price和f_name
select s_id,f_name,f_price from fruits where s_id=101 or s_id=102;
# 在这里,也可以使用I操作符实现与OR相同的功能
select s_id,f_name,f_price from fruits where s_id in(101,102);
10、查询结果不重复
在SELECT语句中,可以使用DISTINCT关键字指示MySQL消除重复的记录值
sql
select distinct 字段名 from 表名
# 示例:查询fruits表中s_id字段的值,返回s_id字段值且不得重复
select distinct s_id from fruits;
11、对查询结果排序
MySQL可以通过在SELECT语句中使用ORDER BY子句对查询的结果进行排序。
(1)单列排序
sql
# 示例:查询f_name字段
select f_name from fruits order by f_name;
(2)多列排序
sql
# 查询fruits表中的f_name和f_price字段,先按f_name排序,再按f_price排序
select f_name,f_price from fruits order by f_name,f_price;
(3)指定排序方向
默认情况下 ,查询数据按字母升序进行排序(A-Z), 但数据的排序并不仅限于此,还可以使用ORDER BY对查询结果进行降序排序(Z-A) 。这可以通过关键字DESC实现
sql
# 示例:查询fruits表中的f_name和f_price字段,对结果按f_price降序方式排序
select f_name,f_price from fruits order by f_price desc;
也可以对多列进行不同的顺序排序
sql
# 示例:查询fruits表,先按f_price降序排列,再按f_name字段升序排列
select f_price,f_name from fruits order by f_price desc,f_name;
12、分组查询
分组查询是对数据按照某个或多个字段进行分组 。MySQL中使用GROUP BY关键字对数据进行分组
sql
[group by 字段] [having <条件表达式>]
# 字段值为进行分组时所依据的列名称;"HAVING<条件表达式>"指定满足表达式限定条件的结果将被显示。
(1)创建分组
GROUP BY 关键字通常和集合函数一起使用,比如 MAX()、MIN()、COUNT()、SUM()、AVG();
在MySQL中,可以在GROUP BY子句中使用**GROUP_CONCAT()**函数,将每个分组中各个字段的值显示出来:
sql
# 示例:根据s_id对fruits表中的数据进行分组
select s_id,count(*) as Total from fruits group by s_id;
# 根据s_id对fruits表中的数据进行分组,将每个供应商的水果名称显示出来
select s_id, group_concat(f_name) as Names from fruits group by s_id;
(2)使用HAVING过滤分组
GROUP BY 可以和HAVING一起限定显示记录所需满足的条件,只有满足条件的分组才会被显示
sql
# 示例:根据s_id对fruits表中的数据进行分组,并显示水果种类大于1的分组信息
select s_id,group_concat(f_name) as Name
from fruits
group by s_id having count(f_name) > 1;
(3)在GROUP BY子句中使用WITH ROLLUP
使用 WITH ROLLUP 关键字之后,在所有查询出的分组记录之后增加一条记录,该记录计算查询出的所有记录的总和,即统计记录数量
sql
# 示例:根据s_id对fruits表中的数据进行分组,并显示记录数量
select s_id,count(*) as Total
from fruits
group by s_id with rollup;
(4)多字段分组
使用GROUP BY可以对多个字段进行分组,GROUP BY关键字后面跟需要分组的字段,MySOL根据多字段的值来进行层次分组,分组层次从左到右,即先按第1个字段分组,然后在第1个字段值相同的记录中再根据第2个字段的值进行分组,以此类推。
sql
# 示例:根据s_id和f_name对fruits表中的数据进行分组
select * from fruits group by s_id,f_name;
(5)GROUP BY和ORDER BY 一起使用
某些情况下先对分组进行排序;为了演示,先创建数据表:
sql
create table orderitems(
o_num int not null,
o_item int not null,
f_id char(10) not null,
quantity int not null,
item_price decimal(8,2) not null,
primary key (o_num,o_item)
);
INSERT INTO orderitems(o_num,o_item,f_id,quantity,item_price) VALUES(30001,1,'a1',10,5.2),
(30001,2,'b2',3,7.6),
(30001,3,'bs1',5,11.2),
(30001,4,'bs2',15,9.2),
(30002,1,'b3',2,20.0),
(30003,1,'co',100,10),
(30004,1,'o2',50,2.50),
(30005,1,'c0',5,10),
(30005,2,'b1',10,8.99),
(30005,3,'a2',10,2.2),
(30005,4,'m1',5,14.99);
# 查询订单价格大于100的订单号和总订单价格
select o_num,sum(quantity * item_price) as ordertoTal
from orderitems
group by o_num
having sum(quantity*item_price) >= 100;
# 可以看到,返回的结果中orderTotal列的总订单价格并没有按照一定顺序显示,接下来使用ORDERBY关键字按总订单价格排序显示结果
select o_num,sum(quantity * item_price) as ordertoTal
from orderitems
group by o_num
having sum(quantity*item_price) >= 100
order by orderTotal;
当使用ROLL UP时,不能同时使用ORDER BY子句进行结果排序,即**++ROLL UP和ORDER BY是互相排斥++**的。
13、使用LIMIT限制查询结果的数量
SELECT返回所有匹配的行,有可能是表中所有的行,若仅仅需要返回第一行或者前几行,可使用 LIMIT关键字
sql
limit [位置偏移量,] 行数
# 示例:显示fruits表查询结果的前4行
select * from fruits limit 4;
如果指定返回记录的开始位置 ,那么返回结果为从"位置偏移量"参数开始的指定行数**,"行数"参数指定返回的记录条数**
sql
# 示例:在fruits表中,返回从第5个记录开始的行数长度为3的记录
select * from fruits limit 4,3;
三、使用集合函数查询
有时候并不需要返回实际表中的数据,而只是对数据进行总结。MySQL提供一些查询功能,可以对获取的数据进行分析和报告
函数 | 作用 |
---|---|
AVG() | 返回某列的平均值 |
COUNT() | 返回某列的行数 |
MAX() | 返回某列的最大值 |
MIN() | 返回某列的最小值 |
SUM() | 返回某列值的和 |
1、COUNT()函数
COUNT())函数统计数据表中包含的记录行的总数 ,或者根据查询结果返回列中包含的数据行数。其使用方法有两种:
- COUNT(*)计算表中总的行数,不管某列是否有数值或者为空值
- COUNT(字段名)计算指定列下总的行数,计算时将忽略空值的行。
sql
# 示例:查询customers表中总的行数
select count(*) as cust_num from customers;
# 查询customers表中有电子邮箱的顾客的总数;为空NULL的不会被计算到
select count(c_email) as email_num from customers;
# 与group by关键字一起使用
select o_num,count(f_id) from orderitems group by o_num;
2、SUM()函数
SUM()是一个求总和的函数,返回指定列值的总和
sql
# 在orderitems表中查询30005号订单一共购买的水果总量
select sum(quantity) as items_total from orderitems where o_num = 30005;
# 与group by关键字一起
# 在orderitems表中,使用SUMO函数统计不同订单号中订购的水果总量
select o_num,sum(quantity) as items_total
from orderitems
group by o_num;
3、AVG()函数
AVG()函数通过计算返回的行数和每一行数据的和 ,求得指定列数据的平均值
sql
# 在fuits表中,査询sid=103的供应商的水果价格的平均值
select avg(f_price) as avg_price from fruits where s_id=103;
# 与group by关键字一起使用
# 在fruits表中,查询每一个供应商的水果价格的平均值
select s_id,avg(f_price) as avg_price from fruits group by s_id;
4、MAX()函数
MAX()返回指定列中的最大值
sql
# 在fruits表中查找市场上价格最高的水果值
select max(f_price) as max_price from fruits;
# 与group by关键字一起使用
# 在fruits表中查找不同供应商的价格最高的水果值
select s_id,max(f_price) as max_price
from fruits group by s_id;
MAX()函数不仅适用于查找数值类型,也可应用于字符类型
sql
# 在fuits表中查找fname的最大值
select max(f_name) from fruits;
5、MIN()函数
MIN()返回查询列中的最小值
sql
# 在fuits表中查找市场上价格最低的水果值
select min(f_price) as min_price from fruits;
# 与group by一起使用
# 在fruits表中查找不同供应商的价格最低的水果值
select s_id,min(f_price) as min_price
from fruits group by s_id;
四、连接查询
连接是关系数据库模型的主要特点。连接查询是关系数据库中最主要的查询,主要包括内连接、外连接等。通过连接运算符可以实现多个表查询
1、内连接查询
内连接 (INNER JOIN)使用比较运算符进行表间某(些)列数据的**++比较操作++** ,并列出这些表中与连接条件相匹配的数据行,组合成新的记录 ,也就是说,在内连接查询中,只有满足条件的记录才能出现在结果关系中。
为了示例,首先创建数据表:
sql
create table suppliers(
s_id int not null auto_increment,
s_name char(50) not null,
s_city char(50) null,
s_zip char(50) null,
s_call char(50) not null,
primary key (s_id)
);
INSERT INTO suppliers(s_id,s_name,s_city,s_zip,s_call)
VALUES(101,'FastFruit Inc.','Tianjin','300000','48075'),
(102,'LT Supplies','chongqing','400000','44333'),(103,'ACME','Shanghai','200000','90046'),
(104,'FNK Inc.','Shangshai','528437','11111'),
(105,'Good Set','Taiyuang','030000','22222'),
(106,'Just Eat Ours','Beijing','010','45678'),
(107,'DK Inc.','Zhengzhou','450000','33332');
在fruits表和suppliers表之间使用内连接查询;通过查看两个表结构,发现其都具有相同类型字段s_id,通过s_id建立联系
sql
# 从fruits表中查询f_name、f_price 字段,从suppliers表中查询s_id、s_name
select suppliers.s_id,s_name,f_name,f_price
from fruits,suppliers WHERE fruits.s_id=suppliers.s_id;
# 下面的内连接查询语句返回与前面完全相同的结果
# 在fruits表和suppliers表之间,使用INNER JOIN语法进行内连接查询,
select suppliers.s_id,s_name,f_name,f_price
from fruits inner join suppliers
on fruits.s_id = suppliers.s_id;
如果在一个连接查询中,++涉及的两个表都是同一个表,这种查询称为自连接查询++。自连接是一种特殊的内连接,它是指相互连接的表在物理上为同一张表,但可以在逻辑上分为两张表;
sql
# 查询f_id='a1'的水果供应商提供的水果种类
select f1.f_id,f1.f_name
from fruits as f1,fruits as f2
where f1.s_id = f2.s_id and f2.f_id='a1';
# 此处查询的两个表是相同的表,为了防止产生二义性,对表使用了别名,uits表第1次出现的别名为f1,第2次出现的别名为2,使用SELECT语句返回列时明确指出返回以为前缀的列的全名,WHERE连接两个表,并按照第2个表的fid对数据进行过滤,返回所需数据。
2、外连接查询
外连接查询将查询多个表中相关联的行,内连接时,返回查询结果集合中仅是符合查询条件和连接条件的行。有时候需要包含没有关联的行中数据,即返回查询结果集合中不仅包含符合连接条件的行,还包括左表(左外连接或左连接)、右表(右外连接或右连接)或两个边接表(全外连接)中的所有数据行。外连接分为左外连接 或左连接和右外连接或右连接:
- LEFT JOIN(左连接):返回包括左表中的所有记录和右表中连接字段相等的记录
- RIGHT JOIN(右连接):返回包括右表中的所有记录和左表中连接字段相等的记录
(1)LEFT JOIN左连接
左连接的结果包括LEFT OUTER 子句中指定的左表的所有行,而不仅仅是连接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果行中,右表的所有选择列表列均为空值
首先创建表与插入数据:
sql
create table orders(
o_num int not null auto_increment,
o_date datetime not null,
c_id int not null,
primary key (o_num)
);
insert into orders(o_num,o_date,c_id)
values(30001,'2008-09-01',10001),
(30002,'2008-09-12',10003),
(30003,'2008-09-30',10004),
(30004,'2008-10-03',10005),
(30005,'2008-10-08',10001);
# 在customers表和orders表中,查询所有客户,包括没有订单的客户
select customers.c_id,orders.o_num
from customers left outer join orders
on customers.c_id=orders.c_id;
(2)RIGHT JOIN右连接
右连接是左连接的反向连接,将返回右表的所有行。如果右表的某行在左表中没有匹配行,左表将返回空值。
sql
# 在customers表和orders表中,查询所有订单,包括没有客户的订单
select customers.c_id,orders.o_num
from customers right outer join orders
on customers.c_id = orders.c_id;
3、复合条件连接查询
复合条件连接查询是在连接查询的过程中,通过添加过滤条件限制查询的结果,使查询的结果更加准确。
sql
# 在customers表和orders表中,使用INNER JOIN语法查询customers表中ID为10001的客户的订单信息
select customers.c_id,orders.o_num
from customers inner join orders
on customers.c_id = orders.c_id and customers.c_id = 10001;
# 使用连接查询,并对查询的结果进行排序
# 在fruits和suppliers表之间,使用inner join语法进行内连接查询,并对查询结果排序
select suppliers.s_id,s_name,f_name,f_price
from fruits inner join suppliers
on fruits.s_id = suppliers.s_id
order by fruits.s_id;
五、子查询
子查询指一个查询语句嵌套在另一个查询语句内部的查询;在SELECT 子句中先计算子查询 ,子查询结果作为外层另一个查询的过滤条件,查询可以基于一个表或者多个表。子查询中常用的操作符有**++ANY(SOME)、ALL、IN、EXISTS++**。子查询可以添加到 SELECT、UPDATE和 DELETE语句中,而且可以进行多层嵌套。子查询中也可以使用比较运算符,如"<" "<=" ">" ">="和"!=";
1、带ANY、SOME关键字的子查询
ANY 和SOME关键字是同义词,表示满足其中任一条件 ,它们允许创建一个表达式对子查询的返回值列表进行比较,只要满足内层子查询中的任何一个比较条件,就返回一个结果作为外层查询的条件
为了示例:先创建表与数据:
sql
create table tb11 (num1 int not null);
create table tb12 (num2 int not null);
insert into tb11 values(1),(5),(13),(27);
insert into tb12 values(6),(14),(11),(20);
ANY 关键字接在一个比较操作符的后面,表示若与子查询返回的任何值比较为TRUE,则返回 TRUE
sql
# 示例:返回tb12表的所有num2列,然后将tb11中的num1的值与之进行比较,只要大于num2的任何一个值,即为符合查询条件的结果
select num1 from tb11 where num1 > any (select num2 from tb12);
2、带ALL关键字的子查询
使用ALL时需要同时满足所有内层查询的条件;ALL关键字接在一个比较操作符的后面,表示与子查询返回的所有值比较为TRUE,则返回TRUE
sql
# 示例:返回tb11表中比tb12表num2列所有值都大的值
select num1 from tb11 where num1 > all (select num2 from tb12);
3、带EXISTS关键字的子查询
EXISTS 关键字后面的参数是一个任意的子查询,系统对子查询进行运算以判断它是否返回行,如果至少返回一行,那么EXISTS的结果为true ,此时外层查询语句将进行查询:如果子查询没有返回任何行,那么EXISTS返回的结果是false,此时外层语句将不进行查询。
sql
# 示例:查询suppliers表中是否存在s_id=107的供应商,若存在则查询fruits表中的记录
select * from fruits where exists
(select s_name from suppliers where s_id=107);
# exits可和条件表达式一起使用
# 查询suppliers表中是否存在s_id=107的供应商,存在则查询fruits表中的f_price大于10.20的记录
select * from fruits where f_price>10.20 and exists
(select s_name from suppliers where s_id=107);
NOT EXISTS与EXISTS使用方法相同,返回的结果相反。子查询如果至少返回一行,那么NOTEXISTS的结果为false,此时外层查询语句将不进行查询:如果子查询没有返回任何行,那么NOTEXISTS返回的结果是true,此时外层语句将进行查询。
sql
# 示例:查询suppliers表中是否存在s_id=107的供应商,不存在则查询fruits表中的记录
select * from fruits where not exists
(select s_name from suppliers where s_id=107);
4、带IN关键字的子查询
IN 关键字进行子查询时,内层查询语句仅仅返回一个数据列 ,这个数据列里的值将提供给外层查询语句进行比较操作
sql
# 在orderitems表中查询f_id为c0的订单号,并根据订单号查询具有订单号的客户c_id
select c_id from orders where o_num in
(select o_num from orderitems where f_id='c0');
# 可使用NOT IN关键字,其作用与IN相反
# 与上一例子相反
select c_id from orders where o_num not in
(select o_num from orderitems where f_id='c0');
5、带比较运算符的子查询
sql
# 在suppliers表中査询s_city等于"Tianjin"的供应商s_id,然后在fruits表中查询所有该供应商提供的水果的种类
select s_id,f_name from fruits
where s_id =
(select s1.s_id from suppliers as s1 where s1.s_city = 'Tianjin')
# 在suppliers表中査询s_city等于"Tianjin"的供应商s_id,然后在fruits表中查询所有非供应商提供的水果的种类
select s_id,f_name from fruits
where s_id <>
(select s1.s_id from suppliers as s1 where s1.s_city = 'Tianjin')
六、合并查询结果
利用 UNION 关键字,可以给出多条 SELECT语句 ,并将它们的结果组合成单个结果集 。合并时,两个表对应的列数和数据类型必须相同 。各个SELECT语句之间使用UNION或UNION ALL关键字分隔。UNION 不使用关键字 ALL,执行的时候删除重复的记录,所有返回的行都是唯一的;使用关键字 ALL的作用是不删除重复行也不对结果进行自动排序。基本语法格式如下:
sql
select column,... from table1
union [all]
select column,... from table2
# 查询所有价格小于9的水果的信息,查询s_id等于101和103所有水果的信息,使用UNION连接查询结果
select s_id,f_name,f_price
from fruits
where f_price < 9.0
union select s_id,f_name,f_price
from fruits
where s_id in(101,103);
使用UNION ALL包含重复的行,在前面的例子中,分开查询时,两个返回结果中有相同的记录。UNION从查询结果集中自动去除了重复的行,如果要返回所有匹配行,而不进行删除,可以使用 UNION ALL。
sql
# 查询所有价格小于9的水果的信息,查询s_id等于101和103所有水果的信息,使用UNION ALL连接查询结果
select s_id,f_name,f_price
from fruits
where f_price < 9.0
union all
select s_id,f_name,f_price
from fruits
where s_id in(101,103);
七、为表和字段取别名
1、为表取别名
当表名字很长或者执行一些特殊查询时,为了方便操作或者需要多次使用相同的表时,可以为表指定别名,用这个别名替代表原来的名称
sql
表名 [AS] 表别名
# 为orders表取别名o,查询30001订单的下单日期
select * from orders as o
where o.o_num = 30001;
# 为customers和orders表分别取别名,并进行连接查询
select c.c_id,o.o_num
from customers as c left outer join orders as o
on c.c_id = o.c_id;
# 自连接示例
select f1.f_id,f1.f_name
from fruits as f1,fruits as f2
where f1.s_id = f2.s_id and f2.f_id = 'a1';
2、为字段取别名
有些情况下,显示的列的名称很长或不直观,可指定列别名
sql
列名 [AS] 列别名
# 示例:查询fruits表,为f_name取别名fruits_name,f_price取别名fruit_price,为fruits标取别名f1,查询表中f_price<8的水果的名称
select f1.f_name as fruits_name,f1.f_price as fruit_price
from fruits as f1
where f1.f_price < 8;
# 也可为子句计算字段取别名,例如,使用count聚合函数或concat等系统函数执行的结果字段取别名
# 查询suppliers表中字段s_name和s_city,使用concat函数连接这两个字段值,并取列别名为suppliers_title
select concat(trim(s_name),'(',trim(s_city),')')
as suppliers_title
from suppliers
order by s_name;
八、使用正则表达式查询
MySOL中使用REGEXP关键字指定正则表达式的字符匹配模式。下面列出REGEXP 操作符中常用字符匹配列表
选项 | 说明 | 例子 | 匹配值示例 |
---|---|---|---|
^ | 匹配文本的开始字符 | '^b'匹配以字母b开头的字符串 | |
$ | 匹配文本的结束字符 | 'st$'匹配以st结尾的字符串 | |
. | 匹配任何单个字符 | 'b.t'匹配任何b和t之间有一个字符的字符串 | |
* | 匹配零个或多个在它前面的字符 | 'f*n'匹配字符n前面有任意个字符f的字符串 | |
+ | 匹配前面的字符1次或多次 | 'ba+'匹配以b开头后面紧跟至少有一个a的字符串 | |
<字符串> | 匹配包含指定的字符串的文本 | 'fa'匹配包含fa的字符串 | |
[字符集合] | 匹配字符集合中的任何一个字符 | '[xz]'匹配包含x或z的字符串 | |
[^] | 匹配不在括号中的任何字符 | '[^abc]'匹配任何不包含a、b或c的字符串 | |
字符串{n,} | 匹配前面的字符串至少n次 | b{2}匹配2个或更多的b | |
字符串{n,m} | 匹配前面的字符串至少n次,至多m次。如果n为0,此参数为可选参数 | b{2,4}匹配含最少2个、最多4个b的字符串 |
1、查询以特定字符或字符串开头的记录
字符'^'匹配以特定字符或者字符串开头的文本
sql
# 示例:在fruits表中,查询f_name字段以字母'b'开头的记录
select * from fruits where f_name regexp '^b';
# 在fruits表中,查询f_name字段以"be"开头的记录
select * from fruits where f_name regexp '^be';
2、查询以特定字符或字符串结尾的记录
字符'$'匹配以特定字符或者字符串结尾的文本
sql
# 在fruits表中,查询f_name字段以字母'y'结尾的记录
select * from fruits where f_name regexp 'y$';
# 在fruits表中,查询f_name字段以字符串'rry'结尾的记录
select * from fruits where f_name regexp 'rry$';
3、用符号'.'来替代字符串中的任意一个字符
字符'.'匹配任意一个字符
sql
# 在fruits表中,查询f_name字段值包含字母'a'与'g'且两个字母之间只有一个字母的记录
select * from fruits where f_name regexp 'a.g';
4、使用'*'和'+'来匹配多个字符
星号'*'匹配前面的字符任意多次,包括0次。加号'+'匹配前面的字符至少一次
sql
# 在fruits表中,查询fname 字段值以字母'b'开头且'b'后面出现字母'a'的记录
select * from fruits where f_name regexp '^ba*';
# 在fruits表中,查询f_name字段值以字母'b'开头且'b'后面出现字母'a'至少一次的记录
select * from fruits where f_name regexp '^ba+';
5、匹配指定字符串
正则表达式可以匹配指定字符串,只要这个字符串在查询文本中即可,如要匹配多个字符串多个字符串之间使用分隔符'|'隔开;
sql
# 在fruits表中,查询f_name字段值包含字符串"on"的记录
select * from fruits where f_name regexp 'on';
# 在fruits表中,查询f_name字段值包含字符'on'或'ap'的记录
select * from fruits where f_name regexp 'on|ap';
LIKE运算符也可以匹配指定的字符串,但与REGEXP不同,LIKE匹配的字符串如果在文本中间出现,则找不到它,相应的行也不会返回。REGEXP 在文本内进行匹配,如果被匹配的字符串在文本中出现,REGEXP将会找到它,相应的行也会被返回。
6、匹配指定字符中的任意一个
方括号"[]"指定一个字符集合,只匹配其中任何一个字符,即为所查找的文本
sql
# 在fruits表中,查找f_name字段中包含字母'o'或't'的记录
select * from fruits where f_name regexp '[ot]';
# 方括号"[]"还可以指定数值集合
# 在fruits表中,查询s_id字段中包含4、5或者6的记录
select * from fruits where s_id regexp '[456]';
7、匹配指定字符以外的字符
"[^字符集合]"匹配不在指定集合中的任何字符
sql
# 在fruits表中,查询f_id字段中包含字母a-e和数字1-2以外字符的记录
select * from fruits where f_id regexp '[^a-e1-2]';
8、使用{n,}或者{n,m}来指定字符串连续出现的次数
"字符串{n,}"表示至少匹配n次前面的字符;"字符串{n,m}"表示匹配前面的字符串不少于n次,不多于m次
sql
# 在fruits表中,查询f_name字段值出现字母'x'至少2次的记录
select * from fruits where f_name regexp 'x{2,}';
# 在fruits表中,查询f_name字段值出现字符串'ba'最少1次、最多3次的记录
select * from fruits where f_name regexp 'ba{1,3}';
九、MySQL新特性
1、GROUP BY不再隐式排序
2、通用表表达式
致谢
在此,我要对所有为知识共享做出贡献的个人和机构表示最深切的感谢。同时也感谢每一位花时间阅读这篇文章的读者,如果文章中有任何错误,欢迎留言指正。
学习永无止境,让我们共同进步!!