xiaoyh 的个人博客

一个只会敲代码的咸鱼

0%

SQL 进阶(2)

先创建一个数据表 access_log

aid site_id count date
1 1 45 2016-05-10
2 3 100 2016-05-13
3 1 230 2016-05-14
4 2 10 2016-05-14
5 5 205 2016-05-14
6 4 13 2016-05-15
7 3 220 2016-05-15
8 5 545 2016-05-16
9 3 201 2016-05-17

GROUP BY 语句

GROUP BY 语句根据一个或多个列对结果集进行分组。在分组的列上可以使用 COUNT、SUM、AVG 等函数。

1
2
3
select col_name, fun(col_name) from table_name
where col_name operator value
group by col_name

实例演示

统计 access_log 中各 site 的访问量

1
2
select site_id, sum(access_log.count) as nums from access_log
group by site_id;
site_id count
1 275
2 10
3 521
4 13
5 750

使用 WITH ROLLUP

WITH ROLLUP 可以实现在分组统计数据基础上再进行相同的统计(SUM、AVG、COUNT 等)

1
2
select site_id, sum(access_log.count) as nums from access_log
group by site_id with rollup;
site_id nums
1 275
2 10
3 521
4 13
5 750
NULL 1571

其中 NULL 表示所有 site_id 的 count 的总和。

可以使用 coalesce(a,b,c) 来设置一个取代 NULL 的名称

如果a == null,则选择b;
如果b == null,则选择c;
如果a != null,则选择a;
如果a b c 都为 null ,则返回为 null。

1
2
select coalesce(site_id, '总访问量'), sum(access_log.count) as nums from access_log
group by site_id with rollup;
site_id nums
1 275
2 10
3 521
4 13
5 750
总访问量 1571

HAVING 子句

HAVING 语句通常与 GROUP BY 语句联合使用,用来筛选由 GROUP BY 语句返回的记录集。

1
2
3
4
select col_name, fun(col_name) from table_name
where col_name operator value
group by col_name
having fun(col_name) operator value;

HAVING 语句的存在弥补了 WHERE 关键字不能与聚合函数联合使用的不足。

实例

查询 access_log 表中 site_id 小于 4 且总访问量大于 200 的数据:

1
2
3
4
select site_id, sum(access_log.count) as nums from access_log
where site_id < 4
group by site_id
having sum(access_log.count) > 200;
site_id nums
1 275
3 521

查询语句执行顺序

一个查询语句同时出现了 WHEREGROUP BYHAVING 等语句的时候,执行顺序是:

  1. FROM <left_table>
  2. ON <join_conditon>(关联条件)
  3. JOIN <right_table>
  4. WHERE <where_conditon>(筛选条件)
  5. GROUP BY <col_name>(分组)
  6. 聚合函数(col_name)(having 子句中的)
  7. HAVING <where_conditon>(分组后筛选条件)
  8. SELECT
  9. DISTINCT(去重)
  10. UNION(合并)
  11. ORDER BY(排序)
  12. LIMIT(截取)

根据以上的顺序,将查询语句分为大致三个顺序:

表拼接(1 ~ 3)

先加载左表,再判断关联条件,加载右表。

先筛后选(4 ~ 8)

一句话总结:先根据条件语句先后筛选数据,再选择指定的字段。

条件语句的执行顺序依次是 WHEREGROUP BYHAVING,这恰好是它们在 SQL 语句中的先后顺序。若 HAVING 中有聚合函数,则先执行聚合函数再执行 HAVING

筛选后,再通过 SELECT 语句查找指定字段

无条件筛选(9 ~ 12)

最后剩下的子句都是没有条件的筛选语句。
这样可以保证效率最高,比如如果在前面排序,显然会对无关的数据进行排序,降低效率。

依次是:去重、合并、排序、范围截取