一 单表操作

表准备和注意事项

create table employee(
id int not null unique auto_increment,
name varchar(20) not null,
sex enum('male','female') not null default 'male', #大部分是男的
age int(3) unsigned not null default 28,
hire_date date not null,
post varchar(50),
post_comment varchar(100),
salary double(15,2),
office int, #一个部门一个屋子
depart_id int
);

insert into employee(name,sex,age,hire_date,post,salary,office,depart_id) values
('egon','male',18,'20170301','老男孩驻沙河办事处外交大使',7300.33,401,1), #以下是教学部
('alex','male',78,'20150302','teacher',1000000.31,401,1),
('wupeiqi','male',81,'20130305','teacher',8300,401,1),
('yuanhao','male',73,'20140701','teacher',3500,401,1),
('liwenzhou','male',28,'20121101','teacher',2100,401,1),
('jingliyang','female',18,'20110211','teacher',9000,401,1),
('jinxin','male',18,'19000301','teacher',30000,401,1),
('成龙','male',48,'20101111','teacher',10000,401,1),

('歪歪','female',48,'20150311','sale',3000.13,402,2),#以下是销售部门
('丫丫','female',38,'20101101','sale',2000.35,402,2),
('丁丁','female',18,'20110312','sale',1000.37,402,2),
('星星','female',18,'20160513','sale',3000.29,402,2),
('格格','female',28,'20170127','sale',4000.33,402,2),

('张野','male',28,'20160311','operation',10000.13,403,3), #以下是运营部门
('程咬金','male',18,'19970312','operation',20000,403,3),
('程咬银','female',18,'20130311','operation',19000,403,3),
('程咬铜','male',18,'20150411','operation',18000,403,3),
('程咬铁','female',18,'20140512','operation',17000,403,3)
;

# 当表字段特别多,展示的时候错乱,可以使用\G分行展示
select * from employee\G;

# 个别同学的电脑在插入中文的时候是会出现乱码或者空白的现象,可以将字符编码,统一设置成GBK

几个重要关键字的执行顺序

# 书写顺序
select id,name from employee where id > 3;
# 执行顺序
from
where
select '''
虽然执行顺序和书写顺序不一致,按照书写顺序的方式写sql
select * 先用*占位
之后补全后面的sql语句
最后将*号替换后你想要的具体字段
'''

where筛选

# 作用:是对整体数据的一个筛选操作
# 1、查询id大于等于3小于等于6的数据
select id,name,age from employee where id>=3 and id<=6;
select id,name,age from employee where id between 3 and 6; 两者等价 # 2、查询薪资是20000或者18000或者17000的数据
select * from employee where salary=20000 or salary=18000 or salary=17000;
select * from employee where salary in (20000,18000,17000); 两者等价 # 3、查询员工姓名中包含字母o的员工的姓名和薪资
'''
模糊查询
like
% 匹配任意多个字符
— 匹配任意单个字符
'''
select name,salary from employee where name like '%o%'; # 4、查询员工姓名是有四个字符组成的,姓名和薪资
select name,salary from employee where name like '____';
select name,salary from employee where char_length(name)=4; # 5、查询id小于3或者id大于6的数据
select * from employee where id not between 3 and 6; # 6、查询薪资不在20000,18000,17000范围的数据
select * from employee where salary not in (20000,18000,17000); # 7、查询岗位描述为空的员工姓名和岗位名,针对null不能用=,用is
select name,post from employee where post_comment is null;

group by 分组

设置严格模式和聚合函数
# 分组实际应用场景,分组应用场景非常多
男女比例
部门平均薪资
国家之间数据统计 # 1 按照部门分组
select * from employee group by post; '''
分组后,最小可操作单元应该是组,还不在是组内的单个数据
上述命令在你没有设置严格模式的时候是可正常执行的,返回的是分组之后,每个组的第一条数据,
但是不符合分组的规范,分组后不应该考虑单个数据,而应该以组为操作单位(分组之后,没办法直接获取
组内单个数据)
如果设置了严格模式,那么上述命令会直接报错
'''
set global sql_mode='strict_trans_tables,only_full_group_by'; 设置严格模式之后,分组默认只能拿到分组的依据
select post from employee group by post;
按照什么分组就只能拿到分组,其他字段不能直接获取,需要借助于一些方法(聚合函数) '''
什么时候需要分组
关键字
每个 平均 最高 最低
聚合函数
max
min
avg
sum
count
'''
案例
# 1.获取每个部门的最高薪资
select post,max(salary) from employee group by post;
select post as '部门', max(salary) as '最高薪资' from employee group by post;
# as可以给字段起别名,也可以直接省略不写,但不推荐
select post '部门', max(salary) '最高薪资' from employee group by post; # 不推荐 # 2.获取每个部门的最低薪资
select post,min(salary) from employee group by post; # 3.获取每个部门的平均薪资
select post,avg(salary) from employee group by post; # 4.获取每个部门的工资总和
select post,sum(salary) from employee group by post; # 5.获取每个部门的人数
select post,count(id) from employee group by post; # 常用,符合逻辑,count是计数的意思 # 6.查询分组之后的部门名称和每个部门下所有的员工姓名
# group_concat 不单单可以支持你获取分组之后的其他字段值,还支持拼接操作
select post,group_concat(name) from employee group by post;
select post,group_concat(name,'_yyds') from employee group by post;
select post,group_concat(name,':',salary) from employee group by post;
# concat 不分组的时候用
select concat('NAME:',name),concat('SAL:',salary) from employee;
#concat_ws 如果多个字段之间的连接符号是相同的情况下,你可以直接使用concat_ws来完成
select concat_ws(':',name,age,sex) from employee;
'''
补充
as 语法不单单可以给字段起别名,还可以给表临时起别名
'''
select emp.id,emp.name from employee as emp; # 7.查询每个人的年薪,12薪
select name,salary*12 from employee;
group_concat()使用

分组注意事项

# 关键字where和group by 同时出现的时候group by必须在where的后面
where先对整体数据进行过滤之后再分组操作
where筛选条件不能使用聚合函数
select id,name,age from employee where max(salary)>3000; # 报错
select max(salary) from employee; # 不分组,默认整体就是一组 # 8.统计各部门年龄在30岁以上的员工平均薪资
1)先求所有年龄大于30岁的员工
select * from employee where age>30;
2)再对结果进行分组
select * from employee where age>30 group by post;
3)整合
select post,avg(salary) from employee where age>30 group by post;

having分组之后的筛选条件

'''
having的语法跟where是一致的
只不过having是在分组之后进行的过滤操作
既having是可以直接使用聚合函数的
'''
# 统计各部门年龄在30岁以上的员工平均工资并且保留平均薪资大于10000的部门
select post,avg(salary) from employee
where age>30
group by post
having avg(salary)>10000;
# 先对各部门年龄在30岁以上的员工平均工资进行分组的基础上,再用having进行过滤

distinct去重

'''
一定要注意,必须是完全一样的数据才可以去重!!!
一定不要将主键忽视,有主键存在的情况下,是不可能去重的 ORM 对象关系映射,让不懂SQL语句的人也能够很好的操作数据
表 类
一条条数据 对象
字段对应的值 对象的属性 写类 创建表
用类生成对象 创建数据
对象点属性 获取数据字段对应的值 目的让懂python面向对象的人也可以操作MySQL
'''
select distinct id,age from employee;  # 有id主键,去不了重
select distinct age from employee;

order by排序

select * from employee order by salary;
select * from employee order by salary asc; # 升序
select * from employee order by salary desc; # 降序
'''
order by默认是升序 asc可以省略不写
也可以改成降序 desc
'''
select * from employee order by age desc,salary asc;
# 先按照age降序排,如果碰到age相同,则再按照salary升序排 # 统计各部门年龄在10岁以上的员工平均工资并且保留平均薪资大于1000的部门,然后对平均工资降序排序
select post,avg(salary) from employee
where age>10
group by post
having avg(salary)>1000
order by avg(salary) desc;

limit限制展示条数

select * from employee;
'''针对数据过多的情况,通常做分页处'''
select * from employee limit 3; # 只展示三条数据
select * from employee limit 0,5;
select * from employee limit 5,5;
'''
第一个参数是起始位置
第二个参数是展示条数
'''

regexp正则

select * from employee where name regexp '^j.*(n|y)$';  # 匹配以j开头,n或y结尾的所有字符,.*贪婪匹配
'''
正则是一门独立的语言
在python中使用re模块
1.re模块中常用的方法
findall:分组优先展示
^j.*(n|y)$
不会展示所有正则表达式匹配到的内容
仅仅展示括号内正则表达式匹配到的内容
math:从头匹配
search:从整体匹配
2.贪婪匹配与非贪婪匹配
正则表达式默认都是贪婪匹配的
将贪婪变成非贪婪只需要在正则表达式后面加?
.* 贪婪
.*? 非贪婪
'''

二 多表操作

前期表准备

# 建表
create table department(
id int,
name varchar(20)
); create table employee1(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') not null default 'male',
age int,
dep_id int
); # 插入数据
insert into department values
(200,'技术'),
(201,'人力资源'),
(202,'销售'),
(203,'运营'); insert into employee1(name,sex,age,dep_id) values
('egon','male',18,200),
('alex','female',48,201),
('wupeiqi','male',38,201),
('yuanhao','female',28,202),
('liwenzhou','male',18,200),
('jingliyang','female',18,204)
;

表查询

select * from department,employee1; # 笛卡尔积

select * from employee1,department where employee1.dep_id=department.id;

'''
MySQL也知道,你在后面查询数据过程中,肯定会经常用到拼表操作
所以特地给你开设了对应的方法
inner join 内连接
left join 左连接
right join 右连接
union 全连接
''' # inner join 内连接
select * from employee1 inner join department on employee1.dep_id=department.id;
# 只拼接两张表中公有的数据部分 # left join 左连接
select * from employee1 left join department on employee1.dep_id=department.id;
# 左表所有的数据都展示出来,没有对应的项就用NULL # right join 右连接
select * from employee1 right join department on employee1.dep_id=department.id;
# 右表所有的数据都展示出来,没有对应的项就用NULL # union 全连接
select * from employee1 left join department on employee1.dep_id=department.id
union
select * from employee1 right join department on employee1.dep_id=department.id;

子查询

'''
子查询就是我们平时解决问题的思路
分步骤解决问题
第一步
第二部
...
将一个查询语句的结果当做另外一个查询语句的条件去用
''' # 查询部门是技术或者人力资源的员工信息
1.先获取部门的id号
2.再去员工表里面筛选出对应的员工
select id from department where name='技术' or name='人力资源';
select name from employee1 where dep_id in (200,201);
两个条语句合起来
select * from employee1 where dep_id in (
select id from department where name='技术' or name='人力资源');

总结

表的查询结果可以作为其他表的查询条件
也可以通过起别名的方式把它作为一张虚拟表跟其他表关联 '''
多表查询两种方式
先拼接表再查询
子查询,一步一步来
''' # 书写sql语句的时候,select后面先用*占位,之后写完再改
# 在写较为复杂的sql语句的时候,不要想着一口气写完,写一点查一点看一点再写(涉及到数据查询相关的语法都不应该一次性写完,不现实)
# 在做多表查询的时候,联表操作和子查询可能会结合使用

三 补充知识点

# 查询平均年龄在25岁以上的部门名称
'''
只要是多表查询,就有两种思路
联表
子查询
'''
# 联表操作
1 先拿到部门和员工表拼接之后的结果
2 分析语义,得出需要进行分组
select department.name from employee1 inner join department
on employee1.dep_id=department.id
group by department.name
having avg (age)>25;
'''涉及到多表操作的时候,一定要加上表的前缀 department.name''' # 子查询
1 拿到平均年龄25岁的dep_id
2 以dep_id为条件,到部门表中筛选名字
select name from department where id in
(select dep_id from employee group by dep_id
having avg(age)>25); # 关键字exists(了解)
只返回布尔值 True False
返回True的时候外层查询语句执行
返回False的时候外层查询语句不再执行
select * from employee1 where exists
(select id from department where id>3); select * from employee1 where exists
(select id from department where id>300); # 不执行

四 Navicat软件

https://www.cr173.com/soft/126934.html

navicat能够充当多个数据库的客户端,本质是对sql语句的图形封装。

navicat图形化界面有时候反应速度较慢,你可以选择刷新或者关闭当前窗口再次打开即可

当你有一些需求该软件无法满足的时候,就自己动手写sql

提示

'''
1.MySQL是不区分大小写
2.MySQL建议所有的关键字写大写(也可以不)
3.MySQL中的注释,有两种
--
#
4.再navicat中快手添加注释和Pycharmy一样
ctr + ?
'''

五 查询练习

student表和course表是 多对多,第三张表是score表

class表和student表是一对多

teacher表和course表是一对多

# 1、查询所有的课程的名称以及对应的任课老师名
SELECT
course.cname,
teacher.tname
FROM
course
INNER JOIN teacher ON course.teacher_id = teacher.tid;
# 2、查询平均成绩大于八十分的同学的姓名和平均成绩
'''
分析
1.成绩表和学生表联表操作
2.按照学生id分组
3.avg(num)>80过滤,取值学生id及对应的平均值
4.上述生成的虚拟表取名为t1,再跟学生表进行连表操作
5.去学生姓名及对应的平均成绩
'''
SELECT
student.sname,
t1.avg_num
FROM
student
INNER JOIN (
SELECT
score.student_id,
avg( num ) AS avg_num
FROM
score
INNER JOIN student ON score.student_id = student.sid
GROUP BY
score.student_id
HAVING
AVG( num ) > 80
) AS t1 ON student.sid = t1.student_id;
# 3、查询没有报李平老师课的学生姓名
# 分步操作
# 1)先找到李平老师教授的课程id
SELECT course.cid FROM teacher inner JOIN course on course.teacher_id=teacher.tid
WHERE teacher.tname='李平老师';
# 2)再找所有报了李平老师课程的学生id(去重)
SELECT DISTINCT student_id FROM score WHERE course_id in
(SELECT course.cid FROM teacher inner JOIN course on course.teacher_id=teacher.tid
WHERE teacher.tname='李平老师');
# 3)之后去学生表里面去反,就可以取到没有报李平老师课程的学生姓名
SELECT
student.sname
FROM
student
WHERE
sid NOT IN (
SELECT DISTINCT
student_id
FROM
score
WHERE
course_id IN ( SELECT course.cid FROM teacher INNER JOIN course ON course.teacher_id = teacher.tid WHERE teacher.tname = '李平老师' )
);
# 4、查询没有同时选修物理课程和体育课程的学生姓名
# (只要选了一门的,选了两门和没有选的都不要)
# 1)先查物理和体育课程的id
SELECT course.cid FROM course WHERE course.cname in ('物理','体育');
# 2)再去获取所有选了物理和体育的学生数据
SELECT * from score WHERE score.course_id in
(SELECT course.cid FROM course WHERE course.cname in ('物理','体育'));
# 3)按照学生分组,利用聚合函数count筛选出只选了一门的学生id
SELECT score.student_id FROM score WHERE score.course_id in
(SELECT course.cid FROM course WHERE course.cname in ('物理','体育'))
GROUP BY score.student_id
HAVING count(score.student_id)=1;
# 4)依照id获取学生姓名
SELECT
student.sname
FROM
student
WHERE
student.sid IN (
SELECT
score.student_id
FROM
score
WHERE
score.course_id IN ( SELECT course.cid FROM course WHERE course.cname IN ( '物理', '体育' ) )
GROUP BY
score.student_id
HAVING
count( score.student_id ) = 1
);
# 5、查询挂科超过两门(包括两门)的学生姓名和班级
# 1)先筛选出分数小于60的数据
SELECT score.student_id FROM score WHERE score.num<60
GROUP BY score.student_id
HAVING count(score.student_id)>=2;
# 2)按照学生分组,对数据进行计数获取大于等于2的数据
SELECT
student.sname,
class.caption
FROM
class
INNER JOIN student ON student.class_id = class.cid
WHERE
student.sid IN (
SELECT
score.student_id
FROM
score
WHERE
score.num < 60 GROUP BY score.student_id HAVING count( score.student_id ) >= 2
);

总结

在解决sql查询问题的时候,不要慌

一步一步慢慢来,最终能够东拼西凑就过关

六 pymysql模块

支持pymysql代码操作数据库MySQL

import pymysql

conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='123',
database='day47',
charset='utf8' # 编码不要加-
) # 链接数据库 cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) # 产生一个游标对象(用来帮助执行命令)
'''
DictCursor,查询结果以字典形式返回
'''
sql = 'select * from employee;'
res = cursor.execute(sql)
# print(res) # 18,返回的数据条数
# execute返回的是你当前sql语句所影响的行数
# 获取命令执行的查询结果
print(cursor.fetchone()) # 只拿一条
print(cursor.fetchall()) # 拿所有
# print(cursor.fetchmany(2)) # 指定拿几条
# print(cursor.fetchone()) # 读取数据类似于文件光标的移动
# cursor.scroll(1, 'relative') # 相对于光标所在的位置继续往后移动1位
# cursor.scroll(1, 'absolute') # 相对于数据的开头往后继续移动1位
# print(cursor.fetchall())

sql注入

利用一些语法的特性,书写一些特点的语句实现固定的语法 MySQL利用的是MySQL注释语法

select * from user where name='xxx' or 1=1 -- skkdjkdjkd' and password=''

日常生活中很多软件的注册的时候都不能含有特殊符号 因为怕你构造出特定的语句入侵数据库,不安全

敏感的数据不要自己拼接,交给execute帮你即可

import pymysql

conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
passwd='123',
database='day48',
charset='utf8'
) # 链接数据库
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor) username = input('>>>')
password = input('>>>')
# sql = "select * from user where name='{}' and password='{}'".format(username, password)
sql = "select * from user where name=%s and password=%s"
# 解决sql注入的问题,不要手动拼接数据,先用%s占位,之后将需要拼接的数据直接交个excute方法即可
print(sql)
rows = cursor.execute(sql, (username, password)) # 自动识别sql里面的%s用后面元组里面的数据替换
if rows:
print('登录成功')
print(cursor.fetchall())
else:
print('用户名密码错误')

pymysql补充

import pymysql

conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='123',
database='day48',
charset='utf8',
autocommit=True # 完整配置
) cursor = conn.cursor(pymysql.cursors.DictCursor) # 建表
# sql = '''create table user(
# id int primary key auto_increment,
# name char(16),
# password int(32)
# )'''
# res = cursor.execute(sql) # 建表
# 增
sql = 'insert into user(name,password) values(%s,%s)'
rows = cursor.execute(sql, ('cy', 123))
rows = cursor.executemany(sql, [('zd', 123), ('dkj', 123), ('xiaobao', 123)]) # 一次性插入N多条数据
# print(rows)
# conn.commit() # # 删除
# sql = 'delete from user where id=1'
# rows = cursor.execute(sql)
# print(rows)
# conn.commit()
#
# # 改
# sql = 'update user set name="lr" where id=1'
# rows = cursor.execute(sql)
# print(rows)
# conn.commit()
#
# # 查
# sql = 'select * from user '
# cursor.execute(sql)
# print(cursor.fetchall()) '''
增删改查中
删改增的操作设计到数据的修改
需要二次确认conn.commit(),或者autocommit修改成True 也可以一次性插入N多条数据
'''

MySQL(单表查询、多表查询、Navicat软件使用、查询练习、pymysql模块)的更多相关文章

  1. Navicat 软件的使用以及pymysql

    Navicat 软件的使用以及pymysql 一.navicate的安装及使用 下载 直接百度搜索navicate ,如下图 连接数据库 新建数据库以及新建表 选中然后鼠标右键 建模 利用navica ...

  2. day43——多表查询、Navicat工具的使用、pymysql模块

    day43 多表查询 笛卡尔积--不经常用 将两表所有的数据一一对应,生成一张大表 select * from dep,emp; # 两个表拼一起 select * from dep,emp wher ...

  3. Navicat,SQL注入,pymysql模块

    # 关键字exists(了解) 只返回布尔值 True False 返回True的时候外层查询语句执行 返回False的时候外层查询语句不再执行 select * from emp where exi ...

  4. MySQL:记录的增删改查、单表查询、约束条件、多表查询、连表、子查询、pymysql模块、MySQL内置功能

    数据操作 插入数据(记录): 用insert: 补充:插入查询结果: insert into 表名(字段1,字段2,...字段n) select (字段1,字段2,...字段n) where ...; ...

  5. mysql单表多表查询

    单表查询语法: select 字段1,字段2... from 表名where 条 件group by fieldhaving 筛选order by 字段limit 限制条数 关键字的优先级:from  ...

  6. MySQL单表查询

    MySQL之单表查询 创建表 # 创建表 mysql> create table company.employee5( id int primary key AUTO_INCREMENT not ...

  7. python mysql 单表查询 多表查询

    一.外键 变种: 三种关系: 多对一 站在左表的角度: (1)一个员工 能不能在 多个部门? 不成立 (2)多个员工 能不能在 一个部门? 成立 只要有一个条件成立:多 对 一或者是1对多 如果两个条 ...

  8. MySQL单表多次查询和多表联合查询,哪个效率高?

    很多高性能的应用都会对关联查询进行分解. 简单地,可以对每个表进行一次单表查询,然后将结果在应用程序中进行关联.例如,下面这个查询: select * from tag join tag_post o ...

  9. MySQL单表多字段模糊查询

    今天工作时遇到一个功能问题:就是输入关键字搜索的字段不只一个字段,比如 我输入: 超天才 ,需要检索出 包含这个关键字的 name . company.job等多个字段.在网上查询了一会就找到了答案. ...

  10. Mysql 单表查询 子查询 关联查询

    数据准备: ## 学院表create table department( d_id int primary key auto_increment, d_name varchar(20) not nul ...

随机推荐

  1. 监听yaml配置

    接下来我们试试从yaml文件中读取配置,当然这不是动态配置分发的好方式 别急,一口吃不成大胖子 这里其实会为大家介绍不少东西: 如何引入第三方库以及配置openresty lua 文件读取 yaml ...

  2. OAuth2 Authorization Server

    基于Spring Security 5 的 Authorization Server的写法 先看演示 pom.xml <?xml version="1.0" encoding ...

  3. Context与Reducer

    Context与Reducer Context是React提供的一种跨组件的通信方案,useContext与useReducer是在React 16.8之后提供的Hooks API,我们可以通过use ...

  4. oracle sqlplus命令详解(官方示例)

    以为内容选自Oracle官方文档,只讲command-line: 规范:<变量名> , {举例} , a | b 枚举可选值,(XX)描述 ------------------------ ...

  5. Spring源码之bean的加载

    目录 1. FactoryBean 的使用 2. 缓存中获取单例 bean: 3. 从 bean 实例获取对象, 4. 获取单例 bean (从缓存加载失败): 5. 创建 bean (createB ...

  6. docker 发布.net core 项目(linux)

    一.准备阶段:前提:一台linux系统,安装好了Docker并启动 1.上传.netcore项目压缩文件 2.解压 注:若没有解压软件,先下载rar解压软件再安装:需注意系统是64位还是32   (下 ...

  7. 【LeetCode二叉树#12】合并二叉树(巩固层序遍历)

    合并二叉树 力扣题目链接(opens new window) 给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠. 你需要将他们合并为一个新的二叉树.合并的规则是如果 ...

  8. 【LeetCode哈希表#4】梦开始的地方:两数之和(map),以及关于容器map的一些代码技巧

    两数之和 力扣题目链接(opens new window) 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种 ...

  9. ABP开发需要用到的命令

    0.命令行在哪里执行? 在Visual Studio的"解决方案资源管理器"的解决方案或者项目上点鼠标右键,选择"在终端中打开". 1.安装abp的命令行 官网 ...

  10. cw attack