Mysql数据分组GROUP BY 和HAVING,与WHERE组合使用

本文介绍了SQL中GROUP BY子句的应用,包括如何对数据进行分组和聚合运算,以及如何利用HAVING子句对分组后的结果进行进一步的筛选。通过具体的MySQL示例展示了不同场景下的分组和过滤技巧。

转载地址:点击打开链接

理解分组,可以这样:对GROUP BY子句后面跟随的列名进行分组,然后对每一个分组而不是整个表进行操作。

举例:在产品表中,检索每一个供应商提供的商品的数量。

mysql> SELECT vend_id,COUNT(*) AS num_prods FROM products GROUP BY vend_id;  
结果:

+---------+-----------+
| vend_id | num_prods |
+---------+-----------+
|    1001 |         3 |
|    1002 |         2 |
|    1003 |         7 |
|    1005 |         2 |
+---------+-----------+
4 rows in set (0.01 sec)

分析:

首先根据vend_id进行分组,然后对每一个分组在进行COUNT聚集。当检索的目的是针对每一个记录进行检索的时候,想到用GROUP BY,例如这里是针对每一个供应商。

GROUP BY的规定:

1、GROUP BY 后面可以包含多个列,这就是嵌套。

2、如果GROUP BY进行了嵌套,数据将在最后一个分组上进行汇总。

3、GROUP BY子句中列出来的每个列必须是检索列或有效的表达式(但不能是聚集函数),如果在SELECT中使用了表达式,则必须在GROUP BY子句中指定相同的表达式。不能使用别名。

4、除了聚集语句外,SELECT语句中的每一个列都必须在GROUP BY子句中给出。

5、如果分组列中具有NULL值,则NULL将作为一个分组返回。如果列中有多个NULL,它们将作为一个分组返回。

6、GROUP BY子句必须在WHERE 子句之后,ORDER BY 子句之前。

过滤分组结果

我们知道WHERE 子句用于过滤结果,但是对于分组的过滤WHERE子句不行。

因为WHERE子句,是针对行的过滤。要对分组结果进行过滤,必须使用HAVING子句,HAVING子句能针对分组的结果进行过滤。

举例:

在订单表中,检索出具有两个以上订单的客户id以及订单数量。

分析:

在这个检索需求中,需要先根据客户id进行分组,然后过滤出订单数量大于2的分组。

mysql> SELECT cust_id,COUNT(*) AS orders FROM orders GROUP BY cust_id HAVING orders>=2;  
结果:

+---------+--------+
| cust_id | orders |
+---------+--------+
|   10001 |      2 |
+---------+--------+
1 row in set (0.00 sec)

与WHERE组合使用(先用WHERE过滤)

有的时候,GROUP BY和WHERE子句也要组合使用。比如:在产品表中检索出能提供2个以上商品,并且价格高于10的供应商。

分析:

首先,检索的是供应商,因此SELECT子句应该是SELECT vend_id

其次,产品表中,有价格这一列,因此对于价格高于10的条件的过滤要使用WHERE子句。SELECT vend_id FROM prodcuts WHERE prod_price>=10.

接着,对vend_id进行分组,这样就可以得到每个vend_id的价格高于10的商品数量,GROUP BY放到WHERE子句后。SELECT vend_id FROM prodcuts WHERE prod_price>=10 GROUP BY vend_id.

最后,对分组的结果过滤,过滤出2个以上商品的分组

mysql> SELECT vend_id,COUNT(*) AS num_prods FROM products WHERE prod_price>=10 GROUP BY vend_id HAVING COUNT(*)>=2; 
结果:

+---------+-----------+
| vend_id | num_prods |
+---------+-----------+
|    1003 |         4 |
|    1005 |         2 |
+---------+-----------+
2 rows in set (0.00 sec)

对分组结果进行排序

在订单明细表中,检索出订单总价格高于等于50的订单号以及订单总价格

mysql> SELECT order_num,SUM(quantity*item_price) AS ordertotal FROM orderitems GROUP BY order_num HAVING SUM(quantity*item_price)>=50 ORDER BY ordertotal;  
结果是:

+-----------+------------+
| order_num | ordertotal |
+-----------+------------+
|     20006 |      55.00 |
|     20008 |     125.00 |
|     20005 |     149.87 |
|     20007 |    1000.00 |
+-----------+------------+
4 rows in set (0.08 sec)

SELECT 子句的顺序

SELECT

FROM 

WHERE

GROUP BY

HAVING

ORDER BY

LIMIT




MySQL 中,`WHERE`、`GROUP BY` `HAVING` 是用于数据筛选分组的关键子句,它们的执行顺序逻辑流程有明确的先后关系,理解这些有助于编写高效且准确的 SQL 查询语句。 ### 执行顺序 MySQL 查询语句中,`WHERE`、`GROUP BY` `HAVING` 的执行顺序如下: 1. **`WHERE` 子句** `WHERE` 用于在查询数据时对原始表中的记录进行过滤,它会在聚合操作之前执行。这意味着只有满足 `WHERE` 条件的行才会被传递到后续的处理阶段 [^1]。 2. **`GROUP BY` 子句** 在 `WHERE` 过滤完成后,数据库会对结果集按照指定的列或表达式进行分组。`GROUP BY` 通常聚合函数(如 `COUNT()`、`SUM()`、`AVG()` 等)一起使用,以对每个分组数据进行汇总计算 [^2]。 3. **`HAVING` 子句** `HAVING` 用于在分组完成之后进一步筛选符合条件的分组。由于 `HAVING` 是在聚合操作之后执行,因此它可以引用聚合函数的结果 [^1]。 ### 示例说明 以下是一个包含 `WHERE`、`GROUP BY` `HAVING` 的 SQL 查询示例: ```sql SELECT SubjectId, COUNT(score) AS '参加考试人数' FROM score WHERE score > 60 GROUP BY SubjectId HAVING COUNT(score) > 4; ``` - **`WHERE score > 60`**:首先筛选出分数大于 60 的记录。 - **`GROUP BY SubjectId`**:将筛选后的记录按照 `SubjectId` 分组。 - **`HAVING COUNT(score) > 4`**:最后筛选出每组中记录数超过 4 的分组。 ### 逻辑流程总结 1. **从原始数据中筛选符合条件的记录** (`WHERE`)。 2. **将筛选后的记录按指定列分组** (`GROUP BY`)。 3. **对分组后的结果进行再次筛选** (`HAVING`)。 这种顺序确保了查询的效率准确性,因为 `WHERE` 减少了需要处理的数据量,而 `HAVING` 则专注于最终的分组结果。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值