我们在查询数据时经常会根据数据的某一特性进行分类获取,这就是这篇文章要记录的两个SELECT的子句:GROUP BY
和HAVING
子句。
GROUP BY
其实我们在上一篇文章中已经使用了GROUP BY
子句,在SQL学习七、聚合函数 ——> SUM()函数 - 返回指定列值的和(总计)中我们计算各类水果的销售额时使用的
SELECT goodsName, SUM(quantity*item_price) AS totalPrice
FROM "oderlist"
GROUP BY goodsName
GROUP BY
子句指示 DBMS按goodsName
排序并分组数据,并计算每个goodsName
的totalPrice
而不是整个表的totalPrice
GROUP BY规定
- 1、
GROUP BY
子句可以包含任意数目的列,因此可以对分组进行嵌套(GROUP BY
子句中嵌套GROUP BY
子句) - 2、如果在
GROUP BY
子句中进行了分组嵌套,数据将在最后知道的分组上进行汇总(即最小分组单元) - 3、
GROUP BY
子句中用来分组的必须是检索列或者有效的表达式(这个表达式不能是汇总函数),如果在SELECT
中使用了表达式,则必须在GROUP BY
子句中指定相同的表达式,且不能使用别名 - 4、大多数SQL实现不允许
GROUP BY
指定的列带有长度可变的数据类型(如文本或备注型字段) - 5、如果分组列中包含具有NULL值的行,则NULL将作为一个分组返回,如果列中有多行NULL值,它们将分为一组
- 6、
GROUP BY
子句必须出现在WHERE
子句之后,ORDER BY
子句之前
过滤分组,HAVING
子句
使用场景:
当我们需要过滤分组聚集值而不是特定行值的时候,WHERE
子句就不起作用了,这时候我们就需要使用HAVING
子句了,也就是说HAVING
子句一般需要结合GROUP BY
子句使用。
- 1、例如:我们想查询销售总额大于250元的水果类型,使用
HAVING
子句我们可以这样查询
SELECT goodsName, SUM(quantity*item_price) AS totalPrice
FROM "oderlist"
GROUP BY goodsName HAVING SUM(quantity*item_price) >250
HAVING
子句一般支持使用别名,例如我们可以这样写SQL,查询的结果是一样的
SELECT goodsName, SUM(quantity*item_price) AS totalPrice
FROM "oderlist"
GROUP BY goodsName HAVING totalPrice >250
如果使用WHERE
子句,就会报错
SELECT goodsName, SUM(quantity*item_price) AS totalPrice
FROM "oderlist"
GROUP BY goodsName WHERE SUM(quantity*item_price) >250
我们也可以这么理解,WHERE
子句用在数据分组前进行过滤,HAVING
子句用在数据分组后进行过滤。这是一个重要的区别
- 2、例如:我们想查询销售总额大于150元的水果类型,但是要排除userId=13的订单(可能是自己下的单或者刷的单,不能反馈市场需求),这时我们就可以使用
HAVING
子句和WHERE
子句结合的SQL
SELECT goodsName, SUM(quantity*item_price) AS totalPrice
FROM "oderlist"
WHERE userId != 13
GROUP BY goodsName HAVING SUM(quantity*item_price) >150
userId != 13
也可以换成 NOT IN (13)
SELECT goodsName, SUM(quantity*item_price) AS totalPrice
FROM "oderlist"
WHERE userId NOT IN (13)
GROUP BY goodsName HAVING SUM(quantity*item_price) >150
分组和排序
第四章笔记记录了排序子句ORDER BY
的使用,这里记录一下排序子句ORDER BY
和分组子句GROUP BY
的组合使用。
-
ORDER BY
---- 对满足条件的的输出数据进行排序 -
GROUP BY
---- 对满足条件的输出数据进行分组,但是输出可能不是分组的顺序
一般在使用 GROUP BY 子句时,应该也给出 ORDER BY 子句。这是保证数据正确排序的唯一方法
- 1、例如:我们想查询销售总额大于150元的水果类型和销售额,但是要排除userId=13的订单(可能是自己下的单或者刷的单,不能反馈市场需求),并按照销售额排序
SELECT goodsName, SUM(quantity*item_price) AS totalPrice
FROM "oderlist"
WHERE userId NOT IN (13)
GROUP BY goodsName HAVING SUM(quantity*item_price) >150
ORDER BY totalPrice DESC
SELECT 子句的顺序
子句 | 功能说明 | 是否必须使用 |
---|---|---|
SELECT | 要返回的列或表达式 | 是 |
FROM | 从中检索数据的表 | 仅在从表选择数据时使用 |
WHERE | 行级过滤 | 否 |
GROUP BY | 分组说明 | 仅在按组计算聚集时使用 |
HAVING | 组级过滤 | 否 |
ORDER BY | 输出排序顺序 | 否 |