前言:忽然意识到SQL混乱的(编译)语法模式。
1.不同的DBMS有不同的BUG和细节的判断。
2.同一语言下,不同出版商的语法会不同。 (oracle和mysql)
3.警告有时是可以忽视的,因为1。(像 order by 和with rollup 是否冲突)
4.使用程度依赖经验,而经验的不确定性意味着不同公司的sql习惯不同。
函数区分:
聚合函数:
又称多行函数、分组函数。
作用于一组数据,对一组数据返回一个值
例:AVG(),SUM(),MIN(),MAX()
单行函数:
例:ABS(),ROUND() 返回绝对值、对 数值进行四舍五入等
排序 ORDER BY
顾名思义对表中一个字段的数据 进行排序。
SELECT last_name, department_id, salary
FROM employees
ORDER BY department_id, salary DESC;
升序:ASD(ascend)
降序:DESC(descend)
1.可以使用列的别名进行排序(WHERE过滤 不行)
2.WHERE要紧贴FROM 后, 在ORDER BY 前
3.只有在前级排序列值相同,才会考虑二级排序。
4.如果没有排序操作,默认按照添加数据的顺序呈现。
分页 LIMIT
永远放在语句末尾
格式1:LIMIT 偏移量,单页数目
格式2:LIMIT 单页数目 offset 偏移量
SELECT *
FROM table
LIMIT(PageNo - 1)*PageSize,PageSize;
#LIMIT [位置偏移量,] 行数
PS:分页在不同的 DBMS 中使用的关键字可能不同。在 MySQL、PostgreSQL、MariaDB 和 SQLite 中使用 LIMIT 关键字,而且需要放到 SELECT 语句的最后面。
在ORACAL等sql中就不是这样子了。
示例:
前10条记录: SELECT * FROM 表名 LIMIT 0,10; 或者SELECT * FROM 表名 LIMIT 10;
第11至20条记录: SELECT * FROM 表名 LIMIT 10,10;
第21至30条记录: SELECT * FROM 表名 LIMIT 20,10;
GROUP BY
将表中数据分成若干组。
放在 WHERE 和 FROM 后面,LIMIT前面。
示例
SELECT department_id,AVG(salary),SUM(salary)
FROM employees
GROUP BY department_id;
SELECT department_id,job_id,AVG(salary)
FROM employees
GROUP BY department_id,job_id; #前后顺序无区别
SELECT中出现的非组函数(聚合函数)的字段必须声明在GROUP BY中。反之,GROUP BY中明的字段可以不出现在SELECT中。
错误示例:
SELECT department_id,job_id,AVG(salary)
FROM employees
GROUP BY department_id; #少了job_id,逻辑不通。
# 部门和工作是包含关系
#按照部门分组,寻找部门和工作;
#由于包含关系,也一定会按照工作分组。
#这一点需要手动写入。
配合with rollup
with rollup是用来在分组统计数据的基础上再进行统计汇总,即用来得到group by的汇总信息。
注意:with rollup 和 order by 不能同时使用。因为汇总信息那一栏 是不能配合 排序的。
HAVING
应用场景:存在聚合函数的情况下过滤数据。
WHERE不能筛选聚合函数条件下的数据。
由于是过滤数据,所以having通常配合group by ,在分好组的情况下进行过滤。单纯对于数据整体而言使用having ,意义不大(相当于求最值数据了)。
示例:
如上,两种方式可以引出对比 (或者说,WHERE存在的意义)
对比 where/having
1.where能直接利用字段筛选,但不能利用聚合函数(分组中的函数)筛选
having必须配合group by 筛选,能利用聚合函数。
(同时使用,where排除的记录不会出现在having的分组中)
2.从关联表中获取数据,WHERE筛选后连接,HAVING 先连接后筛选
WHERE 可以先筛选,用筛选后的较小数据集连接关联表;
HAVING 需要准备好结果集(未被筛选的数据集)进行关联,对该集合进行筛选。
这两者的体量区别 决定了 相同情况下 WHERE执行效率更高。
结论:普通条件用WHERE,包含聚合函数的条件用HAVING。
SQL语句执行过程
FROM -> ON(LEFT/RIGHT JOIN) --> WHERE -> GROUP BY -> HAVING -> SELECT 的字段 -- -> DISTINCT -> ORDER BY -> LIMIT
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 语句执行这些步骤的时候,每个步骤都会产生一个 虚拟表 ,然后将这个虚拟表传入下一个步骤中作为输入。这些步骤隐含在 执行过程中,对于我们来说是不可见的。
执行过程的启发:
1.WHERE相比HAVING的效率,高在哪
从执行顺序上,WHERE在group by分组前就已经对数据完成过滤筛选。数据量减小后再进行分组相较于分组后进行HAVING筛选,效率明显更高。
2.WHERE为什么不能使用聚合函数
聚合函数要配合分组。WHERE执行顺序在order by之前。
3.为何WHERE 不能用别名,ORDER BY和LIMIT可以
SELECT中的别名从顺序上来说只能向后使用,不能向前。
最后:注意SQL关键字顺序