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

致谢

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

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

相关推荐
Eastsea.Chen13 分钟前
MTK Android12 user版本MtkLogger
android·framework
长亭外的少年8 小时前
Kotlin 编译失败问题及解决方案:从守护进程到 Gradle 配置
android·开发语言·kotlin
建群新人小猿10 小时前
会员等级经验问题
android·开发语言·前端·javascript·php
1024小神11 小时前
tauri2.0版本开发苹果ios和安卓android应用,环境搭建和最后编译为apk
android·ios·tauri
兰琛11 小时前
20241121 android中树结构列表(使用recyclerView实现)
android·gitee
Y多了个想法12 小时前
RK3568 android11 适配敦泰触摸屏 FocalTech-ft5526
android·rk3568·触摸屏·tp·敦泰·focaltech·ft5526
NotesChapter13 小时前
Android吸顶效果,并有着ViewPager左右切换
android
_祝你今天愉快14 小时前
分析android :The binary version of its metadata is 1.8.0, expected version is 1.5.
android
暮志未晚Webgl14 小时前
109. UE5 GAS RPG 实现检查点的存档功能
android·java·ue5
麦田里的守望者江15 小时前
KMP 中的 expect 和 actual 声明
android·ios·kotlin