1. 程式人生 > 實用技巧 >資料庫之mysql多表查詢(子查詢)以及pymysql等相關內容-46

資料庫之mysql多表查詢(子查詢)以及pymysql等相關內容-46

1.子查詢in

# 1、in
select * from emp where age=18 or age=38 or age=28;
select * from emp where age in (18,38,28);

# 子查詢的思路
select * from emp where dep_id in
(select id from dep where name="技術" or name="銷售");

# 連結串列的思路
select * from emp inner join dep
on emp.dep_id = dep.id
where dep.name in ("技術","銷售");


# not in不支援null
mysql> select * from dep;
+------+--------------+
| id | name |
+------+--------------+
| 200 | 技術 |
| 201 | 人力資源 |
| 202 | 銷售 |
| 203 | 運營 |
+------+--------------+
4 rows in set (0.00 sec)
mysql> insert into emp values(7,'lili','female',48,null);
Query OK, 1 row affected (0.03 sec)

mysql> select * from emp
-> ;
+----+------------+--------+------+--------+
| id | name | sex | age | dep_id |
+----+------------+--------+------+--------+
| 1 | egon | male | 18 | 200 |
| 2 | alex | female | 48 | 201 |
| 3 | wupeiqi | male | 38 | 201 |
| 4 | yuanhao | female | 28 | 202 |
| 5 | liwenzhou | male | 18 | 200 |
| 6 | jingliyang | female | 18 | 204 |
| 7 | lili | female | 48 | NULL |
+----+------------+--------+------+--------+
7 rows in set (0.00 sec)

mysql>


查詢出有員工的部門,
select * from dep where id in
(select distinct dep_id from emp);

查詢出沒有員工的部門,
select * from dep where id not in
(select distinct dep_id from emp);


select * from dep where id not in
(select distinct dep_id from emp where dep_id is not null);

2.子查詢any和all

# any後也跟子查詢語句,與in不一樣的地方在哪裡
# in (子查詢語句)
# in (值1,值2,值3)
# 而any只能跟子查詢語句
# any必須跟比較運算子配合使用

select * from emp where dep_id in
(select id from dep where name in ("技術","人力資源"));

select * from emp where dep_id = any
(select id from dep where name in ("技術","人力資源"));


select * from emp where dep_id not in
(select id from dep where name in ("技術","人力資源"));

select * from emp where ! (dep_id = any(select id from dep where name in ("技術","人力資源")));


查詢出那些薪資比所有部門的平均薪資都高的員工=》薪資在所有部門平均線以上的狗幣資本家
select * from employee where salary > all
(select avg(salary) from employee where depart_id is not null group by depart_id);

查詢出那些薪資比所有部門的平均薪資都低的員工=》薪資在所有部門平均線以下的無產階級勞苦大眾
select * from employee where salary < all
(select avg(salary) from employee where depart_id is not null group by depart_id);

查詢出那些薪資比任意一個部門的平均薪資高的員工=》薪資在任一部門平均線以上的員工
select * from employee where salary > any
(select avg(salary) from employee where depart_id is not null group by depart_id);


select * from employee where salary < any
(select avg(salary) from employee where depart_id is not null group by depart_id);

3.子查詢exists

# 準備資料
create database db13;

use db13

create table student(
id int primary key auto_increment,
name varchar(16)
);

create table course(
id int primary key auto_increment,
name varchar(16),
comment varchar(20)
);

create table student2course(
id int primary key auto_increment,
sid int,
cid int,
foreign key(sid) references student(id),
foreign key(cid) references course(id)
);


insert into student(name) values
("egon"),
("lili"),
("jack"),
("tom");

insert into course(name,comment) values
("資料庫","資料倉庫"),
("數學","根本學不會"),
("英語","鳥語花香");


insert into student2course(sid,cid) values
(1,1),
(1,2),
(1,3),
(2,1),
(2,2),
(3,2);

準備資料
# exists  vs in
# in的效果 高於 exists
# 見部落格:https://www.cnblogs.com/linhaifeng/articles/7267596.html#_label4

select * from 表1 where exists (select * from 表2);

# 例如:查詢有員工的部門=》
select * from dep where exists (select * from emp where dep.id=emp.dep_id);


# not exists的效果 高於 not in
select * from dep where not exists (select * from emp where 203=emp.dep_id);



# 例:查詢選修了所有課程的學生id、name:

# 實現方式一:選修了三門課程的學生就是選修了所有課程的學生
select s.id,s.name from student as s inner join student2course as sc
on s.id = sc.sid
group by sc.sid
having count(sc.cid) = (select count(id) from course);

# 實現方式二:找到這樣的學生,該學生不存在沒有選修過的課程
select * from student as s where not exists (
select * from course as c where not exists (
select * from student2course as sc where sc.sid = s.id and sc.cid = c.id
)
);


select * from student as s where not exists (
select * from course as c where not exists (
select * from student2course as sc where sc.sid = s.id and sc.cid = c.id
)
);



學生記錄可以過濾出來,一定是子查詢內沒有記錄

for 學生: # s.id=2
for 課程: # c.id=1
for 學生2課程: # sc.sid = 2 and sc.cid = 1
pass

==================================
for sid in [1,2,3,4]:
for cid in [1,2,3]:
(sid,cid)


最外層迴圈一次
# (1,1)
# (1,2)
# (1,3)
最外層迴圈二次
# (2,1)
# (2,2)
# (2,3)
最外層迴圈三次
# (3,1)
# (3,2)
# (3,3)
最外層迴圈四次
# (4,1)
# (4,2)
# (4,3)

===================================
# 例2、查詢沒有選擇所有課程的學生,即沒有全選的學生。=》找出這樣的學生,存在沒有選修過的課程
select * from student as s where exists (
select * from course as c where not exists (
select * from student2course as sc where sc.sid = s.id and sc.cid = c.id
)
);

# 例3、查詢一門課也沒有選的學生=》找出這樣的學生,不存在選修過的課程
select * from student as s where not exists (
select * from course as c where exists (
select * from student2course as sc where sc.sid = s.id and sc.cid = c.id
)
);

# 例4、查詢至少選修了一門課程的學生=》找出這樣的學生,存在選修過課程
select * from student as s where exists (
select * from course as c where exists (
select * from student2course as sc where sc.sid = s.id and sc.cid = c.id
)
);

4.pymysql模組

import pymysql # pip3 install pymysql

conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", password="123", db="db13", charset="utf8mb4")
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

# 記錄=》增刪改
# cursor.execute("insert into student values(%s,%s)",[5,'kkk'])
# cursor.executemany("insert into student values(%s,%s)",[(6,'xxx'),(7,'yyy'),(8,'zzzz')])

cursor.execute("insert into student(name) values(%s)", ['zzz'])
print(cursor.lastrowid)

# cursor.execute("delete from student where id > 6;")

# 記錄=》查
# rows = cursor.execute('select * from student;')
# print(rows)

# line = cursor.fetchone()
# print(line)
# line = cursor.fetchone()
# print(line)
#
# lines = cursor.fetchmany(2)
# print(lines)
# lines = cursor.fetchall()
# print(lines)

# for line in cursor:
# print(line)


# cursor.scroll(3,mode='absolute') # 相對絕對位置移動
# print(cursor.fetchone())
# print(cursor.fetchall())
# cursor.scroll(0,mode='absolute') # 相對絕對位置移動
# print(cursor.fetchall())


# cursor.fetchone()
# cursor.scroll(1,mode='relative') # 相對當前位置移動
# cursor.scroll(0,mode='absolute') # 相對當前位置移動
# print(cursor.fetchone())

conn.commit()
cursor.close()
conn.close()