多表查询
连表查询
要进行连接,那一定涉及两个表,两个表中要有关联条件才能进行连接
内连接 只有表一和表二中的连接条件都满足的时候才能显示出来
inner join on /where 条件
select * from t1 inner join t2 on t1.id =t2.t2_id;
select * from t1,t2 where t1.id = t2.t2_id
左外连接 一定显示左表中所有内容,如果右表中的内容没有符合连接条件就不显示
left join
select * from t1 left join t2 on t1.id = t2.t2_id;
右外连接
right join
select * from t1 right join t2 on t1.id = t2.t2_id
全外连接
select * from t1 left join t2 on t1.id = t2.t2_id
union
select * from t1 right join t2 on t1.id = t2.t2_id
所谓的连表,实际上就是把多张表通过条件的连接,变成一张大表,然后所有的查询条件都和原来一张表是一样的
但是我们要注意两张表中如果字段的名字不同,可以直接使用
但是我们要注意两张表中如果字段的名字相同,需要使用 表名.字段名来表示具体的字段
当表的名字过长的时候,可以对表进行一个临时重命名,重命名之后在本条sql中就可以使用新名字来代替原来的表名了
# table1 : id name sex # table2 : id salary t1_id # select table1.id,table2.id,name,salary from table1 inner join table2 on table1.id = table2.t1_id; # select t1.id,t2.id from table1 t1 inner join table2 t2 on t1.id = t2.t1_id;
子查询
是先查一个表,得到一个结果,这个结果要么是n条,要么是1条,通常是一个字段
用这个结果作为条件去查另外一张表
子查询:结果在哪个表,最后你查的一定是那张表
如果结果是n条:在外层查询中你可能会用到in条件
如果结果是1条:在外层查询中你可以用 = != > < is
索引
加速查询速度
mysql的存储引擎的索引基于 b+树hash做的
innodb b+树 聚集索引/聚簇索引 非聚簇索引
myisam b+树 非聚簇索引
memory hash
b+树做了那些事儿?为什么基于b+树的索引会快?
一颗平衡树
在非叶子节点不存储数据相关的信息,只存放指针 : 让树的高度降低了,所有的数据的寻找的时间是固定的
在叶子节点会直接存储数据或者数据的指针 : 能够直接找到对应的数据
叶子节点的各个数据块之间使用双向链表来连接 : 能够更好的进行范围排序相关的操作
要想缩短树的高度,我们能做的事情
1.就是让每一列的宽度尽量的小
聚簇索引和非聚簇索引
聚簇索引
一张表只能有一个
只在innodb存储引擎中存在
b+树 : 在叶子节点会直接存储数据
所有的数据存储的物理地址是根据索引顺序: 排序快
非聚簇索引
每张表可以有多个
在myisam,innodb中都存在
b+树 : 在叶子节点会存储数据的指针
所有的数据存储的物理地址和索引顺序无关
如果创建多个非聚簇索引,那么insert delete数据都会非常慢,并且占用更多的硬盘和内存
今日内容
在创建表的时候创建索引
CREATE TABLE ind1(
id int primary key,
name char(12),
index ind_name(name)
);
在建表之后添加索引
CREATE TABLE ind2(
id int primary key,
email char(12)
);
CREATE INDEX ind_email on ind2(email);
alter table ind2 add index ind_email(email);
删除索引
DROP INDEX ind_email ON ind2;
索引的基础用法
你设置了哪个字段为索引,那么查找条件就使用这个字段,就能够加速查询
如果我们给id字段创建了索引,但是查找的确实email条件,那么就未命中索引,并不会加速查询
一次sql查询只能用上一个索引id = 1000 and email='eva1000@oldboy'
索引的正确使用
1.如果查询的结果是很多条数据的话我们仍然不能命中索引
> < >= <= != like between and
2. 当我们选定某一列作为索引的时候,这一列必须是区分度比较高的列
如果这一列的内容都是重复的,那么创建了索引也不会有任何的加速效果
3.索引列不能在条件中参与计算
4.对于sql中的or来说,即便找到一个为假的条件也还是要去判断另外的条件是否成立,所以mysql并没有进行优化
所有的查询都是从左向右一次进行的,所以使用了or的条件语句很难命中索引
对于sql中的and,由于只要找到一个为假的条件就可以放弃判断整个语句,所以mysql进行了优化
在所有的and条件中会找到第一个区分度最高的列来使用它的索引,来达到加快查询速度的效果
5.联合索引:最左前缀匹配原则
create index union_ind on s1(id,email,name)
联合索引,第一个索引项是这个索引的姓,每一次查询条件必须带着第一个索引项字段(例id),才能命中联合索引
如果条件中丢失了第一个索引项来创建条件,那么不能命中联合索引
create index union_ind on s1(id,email,name,sex)
id
email,id
id,email,name
id,email,name,sex
id,name # id,sex
id,name,sex
聚集索引 1.纪录的索引顺序与无力顺序相同 因此更适合between and和order by操作 2.叶子结点直接对应数据 从中间级的索引页的索引行直接对应数据页 3.每张表只能创建一个聚集索引 非聚集索引 1.索引顺序和物理顺序无关 2.叶子结点不直接指向数据页 3.每张表可以有多个非聚集索引,需要更多磁盘和内容 多个索引会影响insert和update的速度
使用python操作数据库
import pymysql conn = pymysql.connect( host = 'localhost', port = 3306, user = 'root', password = '123', database = 'homework', charset='utf8' ) cur = conn.cursor(pymysql.cursors.DictCursor) # 设置返回的数据类型是字典 cur = conn.cursor() # 默认返回的数据类型是元组 # cur 数据库操作符 # sql = 'drop table ind1;' # sql = """CREATE TABLE EMPLOYEE ( # FIRST_NAME CHAR(20) NOT NULL, # LAST_NAME CHAR(20), # AGE INT, # SEX CHAR(1), # INCOME FLOAT )""" try: sql = 'select * from class' ret = cur.execute(sql) conn.commit() except: conn.rollback() print(ret) res = cur.fetchone() print(res) ret = cur.fetchmany(2) # res = cur.fetchall() print(ret) cur.close() conn.close()