SQL必知必会-读书笔记(八)

GROUP BY

  1. 分组,可以和聚合函数配合,例如:

    1
    2
    3
    4
    5
    6
    # 统计按照x_id分组后,每个分组的个数。如果不加 GROUP BY,相当于统计所有行的数量
    SELECT
    x_id, count(*) as x_num
    FROM
    your_table
    GROUP BY x_id
  2. GROUP BY子句可以包含任意数目的列,可以进行更精细的分组

  3. 不管有多少列,建立分组时,所有的列都是当成一个整体处理,所以不能从个别的列取回数据

  4. GROUP BY子句的每个列都必须是检索列或有效表达式(不能是聚集函数),如果SELECT中使用了表达式,GROUP BY子句中也要指定相同的表达式,不能使用别名

  5. 大多数SQL不允许GROUP BY列带有长度可变的数据类型(MySQL允许,但是不建议,因为分组时处理字符数据比较慢)

  6. 除聚集计算语句外,SELECT的每一列都必须在GROUP BY子句中给出

  7. 如果分组中包含具有 NULL 值的行,则NULL会作为一个分组返回,如果列中有多行NULL值,它们将会被作为一个分组

  8. GROUP BY必须出现在WHERE语句之后,ORDER BY之前。SQL执行顺序可见本文:SQL执行顺序

HAVING

  1. HAVING和WHERE子句都是用于过滤,HAVING是可以使用聚集函数的,而WHERE不允许,例如

    1
    2
    # 按照letter分组,选出数量大于10的分组
    select letter, count(*) from brand group by letter having count(*) > 10
  2. WHERE过滤的是行,HAVING过滤的是分组

  3. 多数情况下,HAVING和WHERE是非常类似的,如果不指定GROUP BY,多数DBMS会同等对待它们。尽管如此,建议使用HAVING要结合GROUP BY

分组和排序对比

ORDER BY GROUP BY
对产生的输出排序 对行分组,但输出可能不是分组的排序
任意列都可以使用(包括非选择的列) 只能使用选择列或表达式列,而且必须使用每个选择列表达式
不一定需要 如果与聚集函数一起使用列(或表达式),则必须使用,否则聚集表达式会作用于所有行

实际上,建议GROUP BY后使用ORDER BY对分组进行排序