单表查询进阶与多表查询

单表操作

分组查询

group by

分组指的是将所有记录按照某个相同的字段进行分类,比如针对员工信息表的职位分组,或者按照性别进行分组。

用法:

select 聚合函数,选取的字段 from 表名 group by 分组的字段

group by:是分组的关键字,必须和聚合函数一起出现

where 条件语句和 group by 分组语句的先后顺序

​ where > group by > having

聚合函数有:

  • count:求数量
  • sum:求和
  • max:求最大数
  • min:求最小数
  • avg:求平均数

例子:

查询表中所有记录:


mysql> select * from userinfo;
+----+----------+-----+-----------+---------+
| id | name     | age | sarlay    | job     |
+----+----------+-----+-----------+---------+
|  1 | qinyj    |  18 |      0.00 | student |
|  2 | tank     |  18 |  10000.11 | teacher |
|  3 | jack     |  33 |  10000.33 | teacher |
|  4 | jing     |  20 |      1.33 | null    |
|  5 | xxx      |  20 | 100000.33 | teacher |
|  6 | xxx      |  20 |   1000.33 | teacher |
|  7 | xxx      |  20 | 100000.00 | teacher |
|  8 | xxx      |  20 |  10000.00 | teacher |
|  9 | jinggggg |  20 |  10000.00 | teacher |
+----+----------+-----+-----------+---------+
9 rows in set (0.00 sec)
  • 以职业为例进行分组,统计一下teacher和student有多少人
select job,count(*) from userinfo group by job;

select job,count(*) as count from userinfo group by job; 




  • 对职业进行分组,求出每个职业中年龄最大的那个人
select name,max(age) from userinfo group by job;

select name,job,max(age) from userinfo group by job;

  • 求出每个职业中最小年龄的人

select name,job,min(age) from userinfo group by job;

  • 求出每个职业中的年龄总和

select job,sum(age) from userinfo group by job;

  • 求出每个职业中的年龄平均数

select job,avg(age) from userinfo group by job;

having

表示对group by 之后的数据,进行二次筛选

  • 求出每个职业中年龄平均数超过30岁的

select job,avg(age) from userinfo group by job having avg(age) > 20;

升序降序

order by

用法:order by 字段名 asc(升序) desc(降序)

  • 对年龄降序排序

select * from userinfo order by age desc;

  • 对id升序排序

select * from userinfo order by id;

  • 如果对多个字段进行排序,aes,desc:表示先对前者字段进行升序,如果前者字段有相同的行,再对后者字段降序

limit

分页处理

用法:limit offset, size

offset:行数据索引

size:取多少条数据

  • 取5条数据

select * from userinfo limit 0,5;

  • 取第一条数据

select * from userinfo limit 1;

  • 取最后一条数据

select * from userinfo limit 9;

  • 如果不知道有多少行取还最后一条数据

select * from pymysql_test order by id desc limit 1;

总结

单表查询关键字使用顺序:

select * from 表名
	where 条件
	group by 条件
	having 条件
	order by 条件
	limit 条件;
	
where > group by > having > order by > limit

多表操作

什么是外键

外键即一个表的字段关联另一个表的字段

为什么要使用外键

1、 减少内存占用的空间

2、 方便修改,只需要修改一张表,其他的表也会跟着修改

外键创建方法:

constraint 外键名 foreign key (被约束的字段) references 约束的表(约束的字段)

使用外键的三种关系

一对多

一对多的关系 即 员工--部门

一个部门可以有多个员工

一个员工隶属于一个部门

我们拆分出来两张表:部门表和员工表,那么其中肯定要一种关系将两个表联系起来,那么这个关系就是员工隶属于部门的关系,就需要在员工表中标明是属于哪个部门的

先创建部门表

# 创建部门表
create table department(
	id int auto_increment primary key,
    name varchar(32) not null default ''
)charset=utf8;



# 插入部门表数据
insert into department (name) values ("运维部"),("财务部"),("研发部"),("行政部");

select * from department;
# 创建员工表
create table user(
	id int auto_increment primary key,
    name varchar(32) not null default ''
    depart_id int not null default 1,	# 创建外键字段
    
    constraint user_depart foreign key(depart_id) references department(id)	# 关联部门表
)charset=utf8;

# 插入员工表数据
insert into user (name,depart_id) values ("qinyj",1);
insert into user (name,depart_id) values ("qinyj2",2);
insert into user (name,depart_id) values ("qinyj3",3);
insert into user (name,depart_id) values ("qinyj4",4);
insert into user (name,depart_id) values ("qinyj5",1);

# 一个部门可以有多个员工,如果在外键插入不存在的部门id则会报错
insert into user (name,depart_id) values ("qiny6",5);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`school`.`user`, CONSTRAINT `user_depart` FOREIGN KEY (`depart_id`) REFERENCES `department` (`id`))

多对多

多对多的关系 即 相亲系统,男孩和女孩约会

一个女嘉宾可以和多个男嘉宾约会

一个男嘉宾可以和多个女嘉宾约会

我们拆分出来两张表:男嘉宾表和女嘉宾表,那么其中肯定要一种关系将两个表联系起来,那么这个关系就是男女嘉宾约会的信息的关系,就需要来记录这么个东西,那么这个信息在哪个表中记录?

我们可以再创建出来一个表,存放约会信息

# 创建男嘉宾表
create table boy(
	id int auto_increment primary key,
    boy_name varchar(32) not null default ''
)charset=utf8;


# 插入男嘉宾数据
insert into boy (boy_name) values ("张三"), ("李四"), ("老王");

# 创建女嘉宾表
create table girl(
	id int auto_increment primary key,
    girl_name varchar(32) not null default ''
)charset=utf8;

# 插入女嘉宾数据
insert into girl (girl_name) values ("丽丽"),("翠花"),("小红");
# 创建约会信息表
create table b_g_info(
	id int auto_increment primary key,
    boy_id int not null default 1,
    girl_id int not null default 1,
    
    # 创建约会对应信息
    constraint b_g_info_boy foreign key(boy_id) references boy(id),	# 关联男嘉宾id
    constraint b_g_info_girl foreign key(girl_id) references girl(id)	# 关联女嘉宾id
)charset=utf8;

# 插入约会信息数据
insert into b_g_info (boy_id,girl_id) values (1,1),(1,2),(2,2),(2,3);

一对一

一对一的关系 即 人--薪资

一个人有薪资

薪资属于一个人

薪资属于隐私信息,可以写在一张表中,但是隐私信息如果某人去查这个人的信息的话,薪资也会查出来,就会看到这个隐私信息,那么我们为了隐藏这个因此数据,我们可以使用另一张表来保存薪资

user表:
id name

薪资信息是比较敏感的字段,我们需要将此字段单独拆出来,变成一张独立的表priv

priv表:
id salary uid (外键 + unique)

# 创建用户表:
create table usertable(
	id int auto_increment primary key,
    name varchar(32) not null default ''
)charset=utf8;


# 插入用户数据
insert into usertable (name) values ("张三"),("李四"),("老王");
# 创建薪资表
create table privtable(
	id int auto_increment primary key,
    salary int not null default 0,
    uid int unique not null default 1,
    constraint privt_user foreign key (uid) references usertable(id)
)charset=utf8;

# 插入薪资数据
insert into privtable (salary,uid) values (2000,1),(3000,2),(4000,3);

多表联查

  • left join ... on ...
  • right join ... on ...
  • inner join ... on ...

我们按照以上的关系分成了多个表之后,那么我们如何去查询数据呢?

设计到多个表的查询我们可以使用left join

例子(两表查询):

mysql> select * from department;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 运维部    |
|  2 | 财务部    |
|  3 | 研发部    |
|  4 | 行政部    |
+----+-----------+
4 rows in set (0.00 sec)

mysql> select * from user;
+----+--------+-----------+
| id | name   | depart_id |
+----+--------+-----------+
|  1 | qinyj  |         1 |
|  2 | qinyj2 |         2 |
|  3 | qinyj3 |         3 |
|  4 | qinyj4 |         4 |
|  5 | qinyj5 |         1 |
+----+--------+-----------+
5 rows in set (0.00 sec)

  • left join ... on ... 查询员工名称和隶属的部门
select * from department 
	left join user on department.id=depart_id;

select user.name,department.name from department 
	left join user on department.id=depart_id;

select user.name,department.name from department 
	left join user on department.id=depart_id 
	where user.name="qinyj4";

  • right join ... on ... 基本和left join ... on ...使用方式一样
  • inner join ... on ... 基本和left join ... on ...使用方式一样

例子(三表/多表查询):

mysql> select * from boy;
+----+----------+
| id | boy_name |
+----+----------+
|  1 | 张三     |
|  2 | 李四     |
|  3 | 老王     |
+----+----------+
3 rows in set (0.00 sec)

mysql> select * from girl;
+----+-----------+
| id | girl_name |
+----+-----------+
|  1 | 丽丽      |
|  2 | 翠花      |
|  3 | 小红      |
+----+-----------+
3 rows in set (0.00 sec)

mysql> select * from b_g_info;
+----+--------+---------+
| id | boy_id | girl_id |
+----+--------+---------+
|  1 |      1 |       1 |
|  2 |      1 |       2 |
|  3 |      2 |       2 |
|  4 |      2 |       3 |
+----+--------+---------+
4 rows in set (0.00 sec)
  • 查询男女嘉宾约会的姓名
select * from b_g_info 
	left join boy on b_g_info.boy_id=boy.id 
	left join girl on b_g_info.girl_id=girl.id;
	
	
select boy_name,girl_name from b_g_info 
	left join boy on b_g_info.boy_id=boy.id 
	left join girl on b_g_info.girl_id=girl.id;
posted @ 2019-10-30 21:10  GeminiMp  阅读(289)  评论(0编辑  收藏  举报