多表查询和pymysql

多表查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
先将需要使用到的表拼接成一张大表 之后基于单表查询完成
inner join 内连接
left join 左连接
right join 右连接
union 全连接


"""
# 涉及到多表查询的时候 字段名称容易冲突 需要使用表名点字段的方式区分
# inner join:只拼接两张表中共有的部分
select * from emp inner join dep on emp.dep_id = dep.id;
# left join:以左表为基准展示所有的内容 没有的NULL填充
select * from emp left join dep on emp.dep_id = dep.id;
# right join:以右表为基准展示所有的内容 没有的NULL填充
select * from emp right join dep on emp.dep_id = dep.id;
# union:左右表所有的数据都在 没有的NULL填充
select * from emp left join dep on emp.dep_id = dep.id
union
select * from emp right join dep on emp.dep_id = dep.id;

多表查询练习

数据准备

1
wget https://klcc-img-1251900471.cos.ap-chengdu.myqcloud.com/sql/lx.sql

题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
1、查询所有的课程的名称以及对应的任课老师姓名
select course.cname,teacher.tname
from teacher
left join course on course.teacher_id=teacher.tid;

2、查询学生表中男女生各有多少人
select gender,count(gender)
from student
group by gender;

3、查询物理成绩等于100的学生的姓名
select student.sname
from course
join score on course.cid=score.course_id
join student on student.sid=score.student_id
where course.cname='物理' and score.num=100;

4、查询平均成绩大于八十分的同学的姓名和平均成绩
select student.sname,avg(score.num)
from student
join score on student.sid=score.student_id
group by student.sname
having avg(score.num)>80;


5、查询所有学生的学号,姓名,选课数,总成绩
select
student.sid,
student.sname,
count(course.cid),
sum(score.num)
from course
join score on course.cid=score.course_id
right join student on student.sid=score.student_id
group by student.sname
order by student.sid;

# ONLY_FULL_GROUP_BY 有限制 只选择出现在group by后面的列,或者给列增加聚合函数
# set sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

6、 查询姓李老师的个数
select count(tid) from teacher where tname like '李%';


7、 查询没有报李平老师课的学生姓名
select student.sname from student where student.sname not in
(select
distinct(student.sname)
from course
join score on course.cid=score.course_id
right join student on student.sid=score.student_id
left join teacher on teacher.tid=course.teacher_id
where teacher.tname='李平老师');

8、 查询物理课程比生物课程高的学生的学号
select t1.student_id
from
(select
student_id,
num
from student
left join score on score.student_id=student.sid
left join course on course.cid=score.course_id
where course.cname='物理') as t1
join
(select
student_id,
num
from student
left join score on score.student_id=student.sid
left join course on course.cid=score.course_id
where course.cname='生物') as t2
on t1.student_id=t2.student_id
where t1.num > t2.num;


9、 查询没有同时选修物理课程和体育课程的学生姓名
select
*
from student
left join score on score.student_id=student.sid
left join course on course.cid=score.course_id
where course.cid=2 or course.cid=3;


10、查询挂科超过两门(包括两门)的学生姓名和班级
select student.sname ,count(num)
from score
join student on student.sid=score.student_id
join class on class.cid=student.class_id
where score.num<60
group by student.sname
having count(num)>=2;

11、查询选修了所有课程的学生姓名
select
student.sname
from student
join score on score.student_id=student.sid
join course on course.cid=score.course_id
group by student.sname
having count(course.cname)=4;


12、查询李平老师教的课程的所有成绩记录
select
course.cname,
score.num,
student.sname
from course
join score on course.cid=score.course_id
right join student on student.sid=score.student_id
left join teacher on teacher.tid=course.teacher_id
where teacher.tname='李平老师';


13、查询全部学生都选修了的课程号和课程名

14、查询每门课程被选修的次数

15、查询之选修了一门课程的学生姓名和学号

16、查询所有学生考出的成绩并按从高到低排序(成绩去重)

17、查询平均成绩大于85的学生姓名和平均成绩

18、查询生物成绩不及格的学生姓名和对应生物分数

19、查询在所有选修了李平老师课程的学生中,这些课程(李平老师的课程,不是所有课程)平均成绩最高的学生姓名

20、查询每门课程成绩最好的前两名学生姓名

21、查询不同课程但成绩相同的学号,课程号,成绩

22、查询没学过“叶平”老师课程的学生姓名以及选修的课程名称;

23、查询所有选修了学号为1的同学选修过的一门或者多门课程的同学学号和姓名;

24、任课最多的老师中学生单科成绩最高的学生姓名

Python操作MySQL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
pip3 install pymsql

import pymsql

# 连接MySQL服务端
conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='123',
database='db8_2',
charset='utf8'
)
# 产生一个游标对象
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 编写SQL语句
sql = 'select * from teacher'
affect_rows = cursor.execute(sql)
print(affect_rows)
# 获取执行结果
print(cursor.fetchall())

SQL注入问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import pymysql


# 连接MySQL服务端
conn = pymysql.connect(
host='127.0.0.1',
port=3306,
user='root',
password='123',
database='db8_3',
charset='utf8',
autocommit=True # 针对增 改 删自动二次确认
)
# 产生一个游标对象
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 编写SQL语句
username = input('username>>>:').strip()
password = input('password>>>:').strip()
sql = "select * from userinfo where name=%s and pwd=%s"
cursor.execute(sql,(username,password))
data = cursor.fetchall()
if data:
print(data)
print('登录成功')
else:
print('用户名或密码错误')


# 1.只需要用户名也可以登录
# 2.不需要用户名和密码也可以登录

"""
SQL注入的原因 是由于特殊符号的组合会产生特殊的效果
实际生活中 尤其是在注册用户名的时候 会非常明显的提示你很多特殊符号不能用
原因也是一样的
结论:设计到敏感数据部分 不要自己拼接 交给现成的方法拼接即可
"""

# sql = 'insert into userinfo(name,pwd) values("jason","123"),("kevin","321")'
# res = cursor.execute(sql)

# print(res)

"""
在使用代码进行数据操作的时候 不同操作的级别是不一样的
针对查无所谓
针对增 改 删都需要二次确认
conn.commit()
"""