SQL HAVING
时间:2018-11-15 17:45:26 来源:igfitidea点击:
在本教程中,我们将学习如何使用SQL HAVING子句为一组行或聚合指定搜索条件。
SQL HAVING子句介绍
HAVING子句通常与SELECT语句中的GROUP BY子句一起使用,用于根据指定的条件筛选行组。
下面是HAVING子句的语法:
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子句来完成如下查询:
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子句一起使用。
SELECT orderID, COUNT(productID) products FROM orderdetails GROUP BY orderID HAVING products > 5;
使用MAX和MIN函数的SQL HAVING 例子
请看下面的产品表:
要选择每个类别中最贵的产品,可以使用以下查询:
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子句中使用了子查询,以便在外部查询中获得正确的结果。
如果出现下面的报错
[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
解决方法有两种:
- 修改 sql_mode
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;
- 不要选择未聚合的列
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函数,如下所示:
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函数:
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元并且在每一类中最便宜的产品,如下所示:
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;