数据库—表查询

一、单表查询

'''数据准备'''
create table student(
id int primary key auto_increment,
name varchar(64) not null,
gender enum('男','女') not null,
height varchar(64),
area varchar(20) default '中国',
port varchar(20) default '未知',
school varchar(20)
);

insert into student(name,gender,height,area,port,school) values('aaa','女','173.1','甘肃','张掖','清华'),
('bbb','男','183.1','上海','青浦','北大'),
('ccc','男','183.3','北京','朝阳','复旦'),
('ddd','男','185.9','广东','广州','清华'),
('eee','女','168','山东','烟台','北大'),
('fff','女','165','新疆','乌鲁木齐','北大'),
('ggg','男','179','河南','洛阳','清华'),
('hhh','女','166.1','广州','广东','复旦'),
('kkk','男','175','上海','浦东','清华'),
('mmm','女','173.1','上海','浦西','复旦'),
('nnn','女','174.8','哈尔滨','齐齐哈尔','清华'),
('ooo','男','176','江苏','南通','复旦'),
('ppp','女','155','江苏','连云港','清华');

+----+------+--------+--------+-----------+--------------+--------+
| id | name | gender | height | area      | port         | school |
+----+------+--------+--------+-----------+--------------+--------+
|  1 | aaa  | 女     | 173.1  | 甘肃      | 张掖         | 清华   |
|  2 | bbb  | 男     | 183.1  | 上海      | 青浦         | 北大   |
|  3 | ccc  | 男     | 183.3  | 北京      | 朝阳         | 复旦   |
|  4 | ddd  | 男     | 185.9  | 广东      | 广州         | 清华   |
|  5 | eee  | 女     | 168    | 山东      | 烟台         | 北大   |
|  6 | fff  | 女     | 165    | 新疆      | 乌鲁木齐     | 北大   |
|  7 | ggg  | 男     | 179    | 河南      | 洛阳         | 清华   |
|  8 | hhh  | 女     | 166.1  | 广州      | 广东         | 复旦   |
|  9 | kkk  | 男     | 175    | 上海      | 浦东         | 清华   |
| 10 | mmm  | 女     | 173.1  | 上海      | 浦西         | 复旦   |
| 11 | nnn  | 女     | 174.8  | 哈尔滨    | 齐齐哈尔     | 清华   |
| 12 | ooo  | 男     | 176    | 江苏      | 南通         | 复旦   |
| 13 | ppp  | 女     | 155    | 江苏      | 连云港       | 清华   |
+----+------+--------+--------+-----------+--------------+--------+

1.1增删改查

insert [into] 
    [数据库名.]表名[(字段1[, ..., 字段n])] 
values 
    (数据1[, ..., 数据n])[, ..., (数据1[, ..., 数据n])];

delete from [数据库名.]表名 [条件];

updata [数据库名.]表名 set 字段1=值1[, ..., 字段n=值n] [条件];

select [distinct] 字段1 [[as] 别名1],...,字段n [[as] 别名n] from [数据库名.]表名 [条件];

条件

#层层筛选后的结果:
from、where、group by、having、distinct、order by、limit

***********************所有的条件可以缺失,种类可以不全,但是千万不可以乱序*********************

1.2where条件

比较运算符:= 、 < 、 > 、 <= 、 >= 、 !=

eg: select * from student where school = '清华';
+----+------+--------+--------+-----------+--------------+--------+
| id | name | gender | height | area      | port         | school |
+----+------+--------+--------+-----------+--------------+--------+
|  1 | aaa  | 女     | 173.1  | 甘肃      | 张掖         | 清华   |
|  4 | ddd  | 男     | 185.9  | 广东      | 广州         | 清华   |
|  7 | ggg  | 男     | 179    | 河南      | 洛阳         | 清华   |
|  9 | kkk  | 男     | 175    | 上海      | 浦东         | 清华   |
| 11 | nnn  | 女     | 174.8  | 哈尔滨    | 齐齐哈尔     | 清华   |
| 13 | ppp  | 女     | 155    | 江苏      | 连云港       | 清华   |
+----+------+--------+--------+-----------+--------------+--------+

区间运算符:

  • between 1 and 5  :(A~B)
  • in(1,3,5)  :1或3或5
eg: select * from student where id between 1 and 5;  #查询id为1-5的数据 闭合区间 
+----+------+--------+--------+--------+--------+--------+
| id | name | gender | height | area   | port   | school |
+----+------+--------+--------+--------+--------+--------+
|  1 | aaa  | 女     | 173.1  | 甘肃   | 张掖   | 清华   |
|  2 | bbb  | 男     | 183.1  | 上海   | 青浦   | 北大   |
|  3 | ccc  | 男     | 183.3  | 北京   | 朝阳   | 复旦   |
|  4 | ddd  | 男     | 185.9  | 广东   | 广州   | 清华   |
|  5 | eee  | 女     | 168    | 山东   | 烟台   | 北大   |
+----+------+--------+--------+--------+--------+--------+

eg: select * from student where id in(2, 4, 6, 8); # 分离的区间,2,4,6,8都会被显示
+----+------+--------+--------+--------+--------------+--------+
| id | name | gender | height | area   | port         | school |
+----+------+--------+--------+--------+--------------+--------+
|  2 | bbb  | 男     | 183.1  | 上海   | 青浦         | 北大   |
|  4 | ddd  | 男     | 185.9  | 广东   | 广州         | 清华   |
|  6 | fff  | 女     | 165    | 新疆   | 乌鲁木齐     | 北大   |
|  8 | hhh  | 女     | 166.1  | 广州   | 广东         | 复旦   |
+----+------+--------+--------+--------+--------------+--------+

逻辑运算符:and、or、not

eg: select * from student where area="山东" and port="烟台";
+----+------+--------+--------+--------+--------+--------+
| id | name | gender | height | area   | port   | school |
+----+------+--------+--------+--------+--------+--------+
|  5 | eee  | 女     | 168    | 山东   | 烟台   | 北大   |
+----+------+--------+--------+--------+--------+--------+

相似运算符

like  '_a%': _表示一个字符(a前面一个字符),%表示任意字符(a后面任意多个字符)

eg: select * from student where name like '__a';
+----+------+--------+--------+--------+--------+--------+
| id | name | gender | height | area   | port   | school |
+----+------+--------+--------+--------+--------+--------+
|  1 | aaa  | 女     | 173.1  | 甘肃   | 张掖   | 清华   |
+----+------+--------+--------+--------+--------+--------+

eg: select * from student where name like 'k%';
+----+------+--------+--------+--------+--------+--------+
| id | name | gender | height | area   | port   | school |
+----+------+--------+--------+--------+--------+--------+
|  9 | kkk  | 男     | 175    | 上海   | 浦东   | 清华   |
+----+------+--------+--------+--------+--------+--------+

eg: select * from student where name like '_m%';
+----+------+--------+--------+--------+--------+--------+
| id | name | gender | height | area   | port   | school |
+----+------+--------+--------+--------+--------+--------+
| 10 | mmm  | 女     | 173.1  | 上海   | 浦西   | 复旦   |
+----+------+--------+--------+--------+--------+--------+

正则匹配:regexp

'''基于字符串查数据'''
# sql只支持部分正则语法
eg: select * from student where name regexp '.*d';  # 不支持d代表数字,认为d就是普通字符串
eg: select * from student where name regexp '.*[f-k]'; #支持[]语法,[]里面可以写a-z,A-Z,0-9
+----+------+--------+--------+--------+--------------+--------+
| id | name | gender | height | area   | port         | school |
+----+------+--------+--------+--------+--------------+--------+
|  6 | fff  | 女     | 165    | 新疆   | 乌鲁木齐     | 北大   |
|  7 | ggg  | 男     | 179    | 河南   | 洛阳         | 清华   |
|  8 | hhh  | 女     | 166.1  | 广州   | 广东         | 复旦   |
|  9 | kkk  | 男     | 175    | 上海   | 浦东         | 清华   |
+----+------+--------+--------+--------+--------------+--------+

1.3分组与筛选:group by | having

where与having

'''在没有分组的情况下,where与having查询的结果相同'''
'''having可以对 聚合结果 进行筛选'''
eg: select * from student where height > 180;
+----+------+--------+--------+--------+--------+--------+
| id | name | gender | height | area   | port   | school |
+----+------+--------+--------+--------+--------+--------+
|  2 | bbb  | 男     | 183.1  | 上海   | 青浦   | 北大   |
|  3 | ccc  | 男     | 183.3  | 北京   | 朝阳   | 复旦   |
|  4 | ddd  | 男     | 185.9  | 广东   | 广州   | 清华   |
+----+------+--------+--------+--------+--------+--------+

eg: select * from student having height > 180;
+----+------+--------+--------+--------+--------+--------+
| id | name | gender | height | area   | port   | school |
+----+------+--------+--------+--------+--------+--------+
|  2 | bbb  | 男     | 183.1  | 上海   | 青浦   | 北大   |
|  3 | ccc  | 男     | 183.3  | 北京   | 朝阳   | 复旦   |
|  4 | ddd  | 男     | 185.9  | 广东   | 广州   | 清华   |
+----+------+--------+--------+--------+--------+--------+

聚合函数

"""
max():最大值
min():最小值
avg():平均值
sum():和
count():记数
group_concat():组内字段拼接,用来查看组内其他字段
"""
eg:略

分组查询:group by

eg: select * from student group by school; 
+----+------+--------+--------+--------+--------+--------+
| id | name | gender | height | area   | port   | school |
+----+------+--------+--------+--------+--------+--------+
|  2 | bbb  | 男     | 183.1  | 上海   | 青浦   | 北大   |
|  3 | ccc  | 男     | 183.3  | 北京   | 朝阳   | 复旦   |
|  1 | aaa  | 女     | 173.1  | 甘肃   | 张掖   | 清华   |
+----+------+--------+--------+--------+--------+--------+
#这样的分组查询是错误的,因为他只显示了每个组的第一个人
#所以我们要对他进行一些数据库配置操作, 有ONLY_FULL_GROUP_BY之后,让数据库看见如此的语法,直接报错

'''
修改my.ini配置重启mysql服务
sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
'''
'''分组'''
假如将 学校进行分组,分别分为了清华、北大、复旦 这就是分组
eg: 按学校分组,每个学校都有哪些人、姓名、性别、身高、组里一共有多少人

'''聚合'''
就是把多条数据统一处理
每个学校都有哪些人、姓名、性别、身高、组里一共有多少人就是聚合的结果

'''参与分组的字段,也归于 聚合结果'''
也就是分为几个学校这个也算聚合的结果

eg:
select 
    school,
    group_concat(name) 学生,
    max(height) 最高身高,
    min(height) 最低身高,
    avg(height) 平均身高,
    count(gender) 人数
from student group by school;  
+--------+-------------------------+--------------+--------------+--------------------+--------+
| school | 学生                    | 最高身高     | 最低身高     | 平均身高           | 人数   |
+--------+-------------------------+--------------+--------------+--------------------+--------+
| 北大   | bbb,eee,fff             | 183.1        | 165          | 172.03333333333333 |      3 |
| 复旦   | ccc,ooo,hhh,mmm         | 183.3        | 166.1        |            174.625 |      4 |
| 清华   | aaa,nnn,kkk,ggg,ddd,ppp | 185.9        | 155          | 173.79999999999998 |      6 |
+--------+-------------------------+--------------+--------------+--------------------+--------+

eg:
select 
    school,
    max(height) 最高身高
from student group by school;
+--------+--------------+
| school | 最高身高     |
+--------+--------------+
| 北大   | 183.1        |
| 复旦   | 183.3        |
| 清华   | 185.9        |
+--------+--------------+

分组后的having

'''having可以对 聚合结果 再进行筛选,where不可以'''
eg:
select 
    school,
    group_concat(name) 学生,
    max(height) 最高身高,
    min(height) 最低身高,
    avg(height) 平均身高,
    count(gender) 人数
from student group by school having avg(height)<173;  
# having 再一次筛选了avg(height)<173的信息,所以就剩下一条数据了
+--------+-------------+--------------+--------------+--------------------+--------+
| school | 学生        | 最高身高     | 最低身高     | 平均身高           | 人数   |
+--------+-------------+--------------+--------------+--------------------+--------+
| 北大   | bbb,eee,fff | 183.1        | 165          | 172.03333333333333 |      3 |
+--------+-------------+--------------+--------------+--------------------+--------+

1.4 排序

#asc:升序(不写默认升序)
#desc:降序
order by 
主排序字段 [asc|desc], 
次排序字段1 [asc|desc], 
...次排序字段n [asc|desc]

未分组状态

eg:
# 按身高升序
select * from student order by height;
+----+------+--------+--------+-----------+--------------+--------+
| id | name | gender | height | area      | port         | school |
+----+------+--------+--------+-----------+--------------+--------+
| 13 | ppp  | 女     | 155    | 江苏      | 连云港       | 清华   |
|  6 | fff  | 女     | 165    | 新疆      | 乌鲁木齐     | 北大   |
|  8 | hhh  | 女     | 166.1  | 广州      | 广东         | 复旦   |
|  5 | eee  | 女     | 168    | 山东      | 烟台         | 北大   |
| 10 | mmm  | 女     | 173.1  | 上海      | 浦西         | 复旦   |
|  1 | aaa  | 女     | 173.1  | 甘肃      | 张掖         | 清华   |
| 11 | nnn  | 女     | 174.8  | 哈尔滨    | 齐齐哈尔     | 清华   |
|  9 | kkk  | 男     | 175    | 上海      | 浦东         | 清华   |
| 12 | ooo  | 男     | 176    | 江苏      | 南通         | 复旦   |
|  7 | ggg  | 男     | 179    | 河南      | 洛阳         | 清华   |
|  2 | bbb  | 男     | 183.1  | 上海      | 青浦         | 北大   |
|  3 | ccc  | 男     | 183.3  | 北京      | 朝阳         | 复旦   |
|  4 | ddd  | 男     | 185.9  | 广东      | 广州         | 清华   |
+----+------+--------+--------+-----------+--------------+--------+
# 按id降序
select * from student order by id desc;
+----+------+--------+--------+-----------+--------------+--------+
| id | name | gender | height | area      | port         | school |
+----+------+--------+--------+-----------+--------------+--------+
| 13 | ppp  | 女     | 155    | 江苏      | 连云港       | 清华   |
| 12 | ooo  | 男     | 176    | 江苏      | 南通         | 复旦   |
| 11 | nnn  | 女     | 174.8  | 哈尔滨    | 齐齐哈尔     | 清华   |
| 10 | mmm  | 女     | 173.1  | 上海      | 浦西         | 复旦   |
|  9 | kkk  | 男     | 175    | 上海      | 浦东         | 清华   |
|  8 | hhh  | 女     | 166.1  | 广州      | 广东         | 复旦   |
|  7 | ggg  | 男     | 179    | 河南      | 洛阳         | 清华   |
|  6 | fff  | 女     | 165    | 新疆      | 乌鲁木齐     | 北大   |
|  5 | eee  | 女     | 168    | 山东      | 烟台         | 北大   |
|  4 | ddd  | 男     | 185.9  | 广东      | 广州         | 清华   |
|  3 | ccc  | 男     | 183.3  | 北京      | 朝阳         | 复旦   |
|  2 | bbb  | 男     | 183.1  | 上海      | 青浦         | 北大   |
|  1 | aaa  | 女     | 173.1  | 甘肃      | 张掖         | 清华   |
+----+------+--------+--------+-----------+--------------+--------+

eg:
# 按身高降序,如果相同,再按id降序
mysql>: select * from student order by height desc, id desc;
表:略

分组状态

select 
    school,
    group_concat(name) 学生,
    max(height) 最高身高,
    min(height) 最低身高,
    avg(height) 平均身高,
    count(gender) 人数
from student group by school order by max(height) desc;
#先分组之后,对最大身高降序
+--------+-------------------------+--------------+--------------+--------------------+--------+
| school | 学生                    | 最高身高     | 最低身高     | 平均身高           | 人数   |
+--------+-------------------------+--------------+--------------+--------------------+--------+
| 清华   | aaa,nnn,kkk,ggg,ddd,ppp | 185.9        | 155          | 173.79999999999998 |      6 |
| 复旦   | ccc,ooo,hhh,mmm         | 183.3        | 166.1        |            174.625 |      4 |
| 北大   | bbb,eee,fff             | 183.1        | 165          | 172.03333333333333 |      3 |
+--------+-------------------------+--------------+--------------+--------------------+--------+

1.5 limit(限制)

limit 条数

eg:
 select id,name,gender,height,school 
 from student where height<175 
 order by id desc limit 3;
 #只显示前3条数据
+----+------+--------+--------+--------+
| id | name | gender | height | school |
+----+------+--------+--------+--------+
| 13 | ppp  | 女     | 155    | 清华   |
| 11 | nnn  | 女     | 174.8  | 清华   |
| 10 | mmm  | 女     | 173.1  | 复旦   |
+----+------+--------+--------+--------+

limit 偏移量,条数

eg:
 select id,name,gender,height,school 
 from student where height<175 
 order by id desc limit 2,3; 
 #先偏移2条满足条件的记录,再查询3条
 +----+------+--------+--------+--------+
| id | name | gender | height | school |
+----+------+--------+--------+--------+
| 10 | mmm  | 女     | 173.1  | 复旦   |
|  8 | hhh  | 女     | 166.1  | 复旦   |
|  6 | fff  | 女     | 165    | 北大   |
+----+------+--------+--------+--------+

1.6 常用函数

"""
拼接:concat() | concat_ws()
大小写:upper() | lower()
浮点型操作:ceil() | floor() | round()
整型:可以直接运算
"""
eg: select name,area,port from student;

eg: select name as 姓名, concat(area,'-',port) 地址 from student;  # 甘肃-张掖

eg: select name as 姓名, concat_ws('-',area,port,school) 信息 from student;  #  甘肃-张掖-清华

mysql>: select upper(name) 姓名大写,lower(name) 姓名小写 from student;
+--------------+--------------+
| 姓名大写     | 姓名小写     |
+--------------+--------------+
| AAA          | aaa          |
...

eg: select id,name,height,
ceil(height)上身高,
floor(height)下身高,
round(height)四舍五入身高 
from student;
+----+------+--------+-----------+-----------+--------------------+
| id | name | height | 上身高    | 下身高    | 四舍五入身高       |
+----+------+--------+-----------+-----------+--------------------+
|  1 | aaa  | 173.1  |       174 |       173 |                173 |
|  2 | bbb  | 183.1  |       184 |       183 |                183 |
...

mysql>: select name 姓名, height 旧身高, height+1 新身高 from student;
+--------+-----------+-----------+
| 姓名   | 旧身高    | 新身高    |
+--------+-----------+-----------+
| aaa    | 173.1     |     174.1 |
...

1.7 distinct

mysql>: 
create table t1(
    id int,
    x int,
    y int
);

mysql>: insert into t1 values(1, 1, 1), (2, 1, 2), (3, 2, 2), (4, 2, 2);

mysql>: select distinct * from t1;  # 全部数据

mysql>: select distinct x, y from t1;  # 结果 1,1  1,2  2,2

mysql>: select distinct y from t1;  # 结果 1  2

# 总结:distinct对参与查询的所有字段,整体去重(所查的全部字段的值都相同,才认为是重复数据)

二、多表查询

连接

# 连接:将有联系的多张表通过关联(有联系就行,不一定是外键)字段,进行连接,形成一张大表
# 连表查询:在大表的基础上进行查询,就称之为连表查询

# 将表与表建立连接的方式有四种:内连接、左连接、右连接、全连接

一对多数据准备

mysql>: create database db3;
mysql>: use db3;

mysql>: 
create table dep(
    id int primary key auto_increment,
    name varchar(16),
    work varchar(16)
);
create table emp(
    id int primary key auto_increment,
    name varchar(16),
    salary float,
    dep_id int
);
insert into dep values(1, '市场部', '销售'), (2, '教学部', '授课'), (3, '管理部', '开车');
insert into emp(name, salary, dep_id) values('egon', 3.0, 2),('yanghuhu', 2.0, 2),('sanjiang', 10.0, 1),('owen', 88888.0, 2),('liujie', 8.0, 1),('yingjie', 1.2, 0);

笛卡尔积

# 笛卡尔积: 集合 X{a, b} * Y{o, p, q} => Z{{a, o}, {a, p}, {a, q}, {b, o}, {b, p}, {b, q}}

mysql>: select * from emp, dep;

# 总结:是两张表 记录的所有排列组合,数据没有利用价值

内连接

# 关键字:inner join on
# 语法:from A表 inner join B表 on A表.关联字段=B表.关联字段

mysql>: 
select 
    emp.id,emp.name,salary,dep.name,work 
from emp inner join dep on emp.dep_id = dep.id 
order by emp.id;

# 总结:只保留两个表有关联的数据

左连接

# 关键字:left join on
# 语法:from 左表 left join 右表 on 左表.关联字段=右表.关联字段

mysql>: 
select 
    emp.id,emp.name,salary,dep.name,work 
from emp left join dep on emp.dep_id = dep.id 
order by emp.id;

# 总结:保留左表的全部数据,右表有对应数据直接连表显示,没有对应关系空填充

右连接

# 关键字:right join on
# 语法:from A表 right join B表 on A表.关联字段=B表关联字段

mysql>: 
select 
    emp.id,emp.name,salary,dep.name,work 
from emp right join dep on emp.dep_id = dep.id 
order by emp.id;

# 总结:保留右表的全部数据,左表有对应数据直接连表显示,没有对应关系空填充

左右可以相互转化

mysql>: 
select 
    emp.id,emp.name,salary,dep.name,work 
from emp right join dep on emp.dep_id = dep.id 
order by emp.id;

mysql>: 
select 
    emp.id,emp.name,salary,dep.name,work 
from dep left join emp on emp.dep_id = dep.id 
order by emp.id;

# 总结:更换一下左右表的位置,相对应更换左右连接关键字,结果相同

全连接

mysql>: 
select 
    emp.id,emp.name,salary,dep.name,work 
from emp left join dep on emp.dep_id = dep.id 

union

select 
    emp.id,emp.name,salary,dep.name,work 
from emp right join dep on emp.dep_id = dep.id 

order by id;

# 总结:左表右表数据都被保留,彼此有对应关系正常显示,彼此没有对应关系均空填充对方

一对一与一对多情况一致

# 创建一对一 作者与作者详情 表
create table author(
    id int,
    name varchar(64),
    detail_id int
);
create table author_detail(
    id int,
    phone varchar(11)
);
# 填充数据
insert into author values(1, 'Bob', 1), (2, 'Tom', 2), (3, 'ruakei', 0);
insert into author_detail values(1, '13344556677'), (2, '14466779988'), (3, '12344332255');

# 内连
select author.id,name,phone from author join author_detail on author.detail_id = author_detail.id order by author.id;

# 全连
select author.id,name,phone from author left join author_detail on author.detail_id = author_detail.id
union
select author.id,name,phone from author right join author_detail on author.detail_id = author_detail.id
order by id;

多对多:两表两表建立连接

# 在一对一基础上,建立 作者与书 的多对多关系关系

# 利用之前的作者表
create table author(
    id int,
    name varchar(64),
    detail_id int
);
insert into author values(1, 'Bob', 1), (2, 'Tom', 2), (3, 'ruakei', 0);

# 创建新的书表
create table book(
    id int,
    name varchar(64),
    price decimal(5,2)
);
insert into book values(1, 'python', 3.66), (2, 'Linux', 2.66), (3, 'Go', 4.66);

# 创建 作者与书 的关系表
create table author_book(
    id int,
    author_id int,
    book_id int
);
# 数据:author-book:1-1,2  2-2,3  3-1,3
insert into author_book values(1,1,1),(2,1,2),(3,2,2),(4,2,3),(5,3,1),(6,3,3);

# 将有关联的表一一建立连接,查询所以自己所需字段
select book.name, book.price, author.name, author_detail.phone from book 
join author_book on book.id = author_book.book_id
join author on author_book.author_id = author.id
left join author_detail on author.detail_id = author_detail.id;
原文地址:https://www.cnblogs.com/lulingjie/p/11654824.html