一、设计数据表的原则
1.考虑的问题
1.用户需要什么数据?
2.需要在数据表中保存哪些数据?
3.哪些数据是经常访问的数据?
4.如何提升检索效率?
2.三少一多原则
a.数据表的个数越少越好
数据表越少,证明实体和联系设计的越简洁。
b.数据表中的字段个数越少越好
不要存在,某个字段的取值可以由其他字段计算出来。
当然字段少是相对的,我们通过会在数据冗余和检索效率中进行平衡。
c.数据表中的联合主键的字段个数越少越好
设值主键是为了确定唯一性,当一个字段无法确定唯一性的时候,就需要采用联合主键的方式。(多个字段来定义一个主键)
联合主键的字段越多,占用的索引空间越大,不仅会增加理解难度,还会增加运行时间和索引空间,因此联合主键的字段越少越好。
d.使用主键和外键越多越好
复用原则,通过主键和外键的使用来增强数据表之间的复用率。因为一个主键可以理解为一张表的代表。键设置的越多,证明它们之间的利用率越高。
二、mysql 检索数据
1.去掉重复行
Disinct使用的注意点:
a. Distinct需要放在所有列名的前面
如果写成
代码语言:javascript复制select name,DINSTINCT sex from students;
则会报错。
b.DISTINCT工作原理
dinstinct 其实是对后面所有列名的组合进行去重。
2.约束查询的好处
可以减少数据表的网络传输量,也可以提升查询效率。
3.select的执行顺序
a.关键字的顺序不能颠倒
代码语言:javascript复制select ... from ... where ... group by ... having ... order by ...
b.select 执行顺序
代码语言:javascript复制from > where > group by > having > select 的字段 > distinct > order by > limit
比如你写了一个sql语句,那么它的关键字顺序和执行顺序是下面这样的:
代码语言:javascript复制SELECT DISTINCT player_id, player_name, count(*) as num # 顺序 5
FROM player JOIN team ON player.team_id = team.team_id # 顺序 1
WHERE height > 1.80 # 顺序 2
GROUP BY player.team_id # 顺序 3
HAVING num > 2 # 顺序 4
ORDER BY num DESC # 顺序 6
LIMIT 2 # 顺序 7
在select 语句 执行这些步骤的时候,每个步骤都会产生一个虚拟表,然后将这个虚拟表传入下一个步骤中作为输入。需要注意的时候,这些步骤隐含在sql的执行过程中,对我们来说并不可见。
c.sql的执行原理
首先,你可以注意到,select是先执行from这一步的。在这个阶段,如果是多表联查,还会经历如下几个步骤:
- 首先,先通过cross join求笛卡儿积,相当于得到虚拟表(vitual table)
vt1-1
; - 通过
on
进行筛选,在虚拟表vt1-1
的基础上进行筛选,得到虚拟表vt1-2
; - 添加外部行。如果我们使用的是左连接,右连接或者全连接,就会涉及到外部行,也就是在虚拟表
vt1-2
的基础上增加外部行,得到虚拟表vt1-3
;
当然,如果我们操作的是两张表以上的表,还会重复上面的步骤,直到所有表都被处理完为止。这个过程得到的是我们的原始数据。
当我们拿到了查询数据表的原始数据,也就是最终的虚拟表vt1
,就可以在此基础上再进行where阶段。在这个阶段中,会根据vt1
表的结果进行筛选过滤,得到表vt2
.
然后进入第三步和第四步,也就是group和having阶段。在这个阶段中,时间上是在虚拟表vt2
的基础上进行分组和分组过滤,得到中间的虚拟表vt3
和vt4
。
当我们完成了条件筛选部分之后,据可以筛选表中提取的字段,也就是进入到select和distinct阶段。
- 首先,在select阶段会提取想要的字段,然后在distinct阶段过滤掉重复的行,分别得到中间的虚拟表
vt5-1
和vt5-2
; - 当我们提取了想要的字段数据后,就可以按照指定的字段进行排序,也就是order by阶段,得到虚拟表
vt6
; - 最后在
vt6
的基础上,取出指定行的记录,也就是limit阶段,得到最终的结果,对应的是虚拟表vt7
;
当然,我们在写select语句的时候,不一定存在所有的关键字,相应的阶段就会省略掉。