SQL
执行顺序
FROM -> WHERE -> GROUP BY -> HAVING -> SELECT -> WINDOW -> DISTINCT -> ORDER BY -> LIMIT
Idx | Seg | Desc |
---|---|---|
1 | FROM | 数据源表 |
2 | WHERE | 条件过滤 |
3 | GROUP BY | 分组 |
4 | HAVING | 过滤聚合结果 |
5 | SELECT | 选择返回列 |
6 | WINDOW | 窗口函数 |
7 | DISTINCT | 去重 |
8 | UNOIN | 组合 |
9 | ORDER BY | 排序 |
10 | LIMIT | 分页 |
顺序
书写顺序不等于执行顺序
别名
SELECT 中的别名可以在 ORDER BY 中使用,不能在 WHERE、GROUP BY、HAVING 中使用。
聚合过滤
WHERE 中不能使用聚合函数,HAVING 子句用于过滤聚合结果。
性能优化
- 尽可能在
WHERE
过滤时减少数据处理量, JOIN
关联使用小表驱动大表GROUP BY
使用索引列分组LIMIT
早使用减少数据处理量
窗口函数
窗口函数(Window Function)基于一个滑动窗口,也就是与当前行相关的一组数据行为其计算出一个结果;通常也称为分析函数(Analytic Function)。
sql
window_function(ex) OVER (
[PARTITION BY partition_expr...]
[ORDER BY order_expr...]
[frame_clause]
)
PARTITION BY
PARTITION BY 选项用于定义分区,作用类似于 GROUP BY 分组;如果指定了分区选项,窗口函数将会分别针对每个分区单独进行分析;否则,所有数据作为一个整体进行分析。
ORDER BY
ORDER BY 选项用于指定分区内的排序方式,与 ORDER BY 子句的作用类似;排序选项通常用于数据的排名分析。
frame_clause
frame_clause 选项用于指定一个滑动的窗口。窗口总是位于分区范围之内,是分区的一个子集。指定了窗口之后,分析函数不再基于分区进行计算,而是基于窗口内的数据进行计算。
ROWS | RANGE | GROUPS BETWEEN frame_start AND frame_end
- ROWS 表示以行为单位计算窗口的偏移量
- RANGE 表示以数值为单位计算窗口的偏移量;
- GROUPS 以组(ORDER BY 排序相同的数据为一组)为单位计算窗口的偏移量,只有 PostgreSQL、SQLite 支持 GROUPS 选项。
frame_start 用于定义窗口的起始位置:
- UNBOUNDED PRECEDING,窗口从分区的第一行开始;
- N PRECEDING,窗口从当前行之前的第 N 行、范围 N 之内或者第 N 个组开始;
- CURRENT ROW,窗口从当前行开始。
frame_end 用于定义窗口的结束位置:
- CURRENT ROW,窗口到当前行结束;
- M FOLLOWING,窗口到当前行之后的第 M 行、范围 M 之内或者第 M 个组结束;
- UNBOUNDED FOLLOWING,窗口到分区的最后一行结束。
ty | fun | desc |
---|---|---|
排序 | ROW_NUMBER() | 为分区中的每行数据分配一个唯一序列号,从 1 开始分配。 |
排序 | RANK() | 计算每行数据在其分区中的名次;如果存在名次相同的数据,后续的排名将会产生跳跃。 |
排序 | DENSE_RANK() | 计算每行数据在其分区中的名次;存在名次相同的数据,后续的排名不会跳跃。 |
排序 | PERCENT_RANK() | 以百分比的形式显示每行数据的名次,取值范围 [0-1]。 |
排序 | CUME_DIST() | 计算每行数据在其分区内的累积分布也就是排在该行数据之前的所有数据所占的比率,取值范围 (0-1]。 |
排序 | NTILE(n) | 将分区内的数据分为 N 等份,为每行数据计算其所在的位置。 |
取数 | FIRST_VALUE(expr) | 返回窗口内第一行对应的 expr 。 |
取数 | LAST_VALUE(expr) | 返回窗口内最后一行对应的 expr 。 |
取数 | LAG(expr, offset, default) | 返回分区中当前行之前第 offset 行对应的 expr 。 offset 和 default 可选,默认值分别为 1 和 NULL。 |
取数 | LEAD(expr, offset, default) | 返回分区中当前行之后第 offset 行的对应expr 。offset 和 default 可选,默认值分别为 1 和 NULL。 |
取数 | NTH_VALUE(expr, n) | 返回窗口内第 n 行对应的 expr 。 |
聚合 | AVG(expr) | 窗口内数据行的平均值。 |
聚合 | SUM(expr) | 窗口内数据行的和值。 |
聚合 | COUNT(expr) | 窗口内数据行的计数。 |
聚合 | MAX(expr) | 窗口内数据行的最大值。 |
聚合 | MIN(expr) | 窗口内数据行的最小值。 |
- 排名窗口函数不支持动态的窗口大小(frame_clause),而是以整个分区(PARTITION BY)作为分析的窗口。
Ref
窗口函数