SQL HAVING


在本教程中,我们将学习如何使用SQL HAVING子句为一组行或聚合指定搜索条件。

SQL HAVING子句介绍

HAVING子句通常与SELECT语句中的GROUP BY子句一起使用,用于根据指定的条件筛选行组。

下面是HAVING子句的语法:

1
2
3
4
5
6
SELECT
column1, column2, aggregate_function(expr)
FROM
table
GROUP BY column1
HAVING condition;

如果HAVING子句没有与GROUP BY子句一起使用,那么它的工作原理与WHERE子句类似。
HAVING子句和WHERE子句的区别在于WHERE子句用于过滤行,而HAVING子句用于过滤行组。

使用SUM函数的SQL HAVING 例子

在这个例子中,我们将查找销售订单的总销售额大于$10000的。我们使用与GROUP BY子句的HAVING子句来完成如下查询:

1
2
3
4
5
6
SELECT
orderid, SUM(unitPrice * quantity) Total
FROM
orderdetails
GROUP BY orderid
HAVING total > 10000;

数据库引擎将执行下面的操作:
首先,对于每个订单行,SQL使用SUM函数计算总金额。(列别名Total用于格式化输出)。
其次,GROUP BY子句根据orderid对所选行进行分组。对于每个订单,我们只有一个包含OrderID和Total的组
第三,HAVING子句获取总数大于10000的组。

使用COUNT函数的SQL HAVING 例子

下面的查询选择至少包含5项产品的所有订单。我们将COUNT函数与HAVING和GROUP BY子句一起使用。

1
2
3
4
5
6
SELECT
orderID, COUNT(productID) products
FROM
orderdetails
GROUP BY orderID
HAVING products > 5;

使用MAX和MIN函数的SQL HAVING 例子

请看下面的产品表:

要选择每个类别中最贵的产品,可以使用以下查询:

1
2
3
4
5
6
7
8
9
10
11
12
13
SELECT
categoryID, productID, productName, MAX(unitprice)
FROM
products A
WHERE
unitprice = (
SELECT
MAX(unitprice)
FROM
products B
WHERE
B.categoryId = A.categoryID)
GROUP BY categoryID;

请注意,语句的WHERE子句中使用了子查询,以便在外部查询中获得正确的结果。

如果出现下面的报错

1
[Err] 1055 - Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'jpetstore.A.ProductID' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

这是因为 如果启用了ONLY_FULL_GROUP_BY SQL模式(默认情况下为该模式),MySQL将拒绝select list、HAVING condition或ORDER BY list引用未聚合列的查询,这些列既不在groupby子句中命名,也不在功能上依赖于这些列。
详细请查看https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html

解决方法有两种:

  1. 修改 sql_mode
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
SELECT
categoryID, productID, productName, MAX(unitprice)
FROM
products A
WHERE
unitprice = (
SELECT
MAX(unitprice)
FROM
products B
WHERE
B.categoryId = A.categoryID)
GROUP BY categoryID;

  1. 不要选择未聚合的列
1
2
3
4
5
6
7
8
9
10
11
12
13
SELECT
categoryID, MAX(unitprice)
FROM
products A
WHERE
unitprice = (
SELECT
MAX(unitprice)
FROM
products B
WHERE
B.categoryId = A.categoryID)
GROUP BY categoryID;

对于每个类别,要选择价格大于120元的最贵产品,可以使用HAVING子句中的MAX函数,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT
categoryID, productID, productName, MAX(unitprice)
FROM
products A
WHERE
unitprice = (
SELECT
MAX(unitprice)
FROM
products B
WHERE
B.categoryId = A.categoryID)
GROUP BY categoryID
HAVING MAX(unitprice) > 120;

要选择在每一类中最便宜的产品,我们可以使用MIN函数替换MAX函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
SELECT
categoryID, productID, productName, MIN(unitprice)
FROM
products A
WHERE
unitprice = (
SELECT
MIN(unitprice)
FROM
products B
WHERE
B.categoryId = A.categoryID)
GROUP BY categoryID

使用HAVING子句中的MIN函数,我们可以找到单价低于5元并且在每一类中最便宜的产品,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT
categoryID, productID, productName, MIN(unitprice)
FROM
products A
WHERE
unitprice = (
SELECT
MIN(unitprice)
FROM
products B
WHERE
B.categoryId = A.categoryID)
GROUP BY categoryID
HAVING MIN(unitprice) < 5;


原文链接:https://codingdict.com/