MySQL--查询数据

前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除

一、基本查询语句

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、通用表表达式

致谢

在此,我要对所有为知识共享做出贡献的个人和机构表示最深切的感谢。同时也感谢每一位花时间阅读这篇文章的读者,如果文章中有任何错误,欢迎留言指正。

学习永无止境,让我们共同进步!!

相关推荐
openinstall全渠道统计2 小时前
免填邀请码工具:赋能六大核心场景,重构App增长新模型
android·ios·harmonyos
双鱼大猫3 小时前
一句话说透Android里面的ServiceManager的注册服务
android
双鱼大猫3 小时前
一句话说透Android里面的查找服务
android
双鱼大猫3 小时前
一句话说透Android里面的SystemServer进程的作用
android
双鱼大猫3 小时前
一句话说透Android里面的View的绘制流程和实现原理
android
双鱼大猫4 小时前
一句话说透Android里面的Window的内部机制
android
双鱼大猫4 小时前
一句话说透Android里面的为什么要设计Window?
android
双鱼大猫4 小时前
一句话说透Android里面的主线程创建时机,frameworks层面分析
android
苏金标5 小时前
android 快速定位当前页面
android
雾里看山8 小时前
【MySQL】内置函数
android·数据库·mysql