1.HAVING 和WHERE 的区别

本文探讨了SQL查询中WHERE和HAVING子句的区别。WHERE用于在分组前筛选数据,而HAVING则在应用聚合函数后对分组结果进行过滤。这两个子句分别在数据处理的不同阶段起作用,理解它们的差异对于优化SQL查询至关重要。

 1.WHERE的情况

SELECT Sname,COUNT(SC.Cno),SUM(Ccredit),AVG(Grade)
FROM SC,C,S
WHERE SC.Cno=C.Cno AND SC.Sno=S.Sno
GROUP BY S.Sno,Sname;

 2.HAVING 的情况

SELECT Sname,COUNT(SC.Cno),SUM(Ccredit),AVG(Grade)
FROM SC,C,S
GROUP BY Sname,S.Sno,SC.Sno,SC.Cno,C.cno HAVING SC.Sno=S.Sno AND SC.Cno=C.Cno;

 为什么会出现两种不同的情况?

1.HAVING 是对GROUP BY 的分组进行作用,是在聚集函数作用之后发生作用,也就是作用在GROUP BY之后。

2.WHERE 是对分组前的数据进行作用,也就是作用在GROUP BY 之前。

3.(来自教科书:数据库系统概论):WHERE 子句作用于基本表或视图,从中选出满足条件的组。HAIVNG短语作用于组,从中选择满足条件的组。

在 PostgreSQL(以及 SQL 标准)中,`WHERE` `HAVING` 都用于过滤数据,但它们的使用场景执行时机有本质区别。理解它们的区别对于正确编写聚合查询至关重要。 --- ### ✅ 区别总结: | 特性 | `WHERE` | `HAVING` | |------|--------|---------| | 作用对象 | 行(原始数据行) | 分组后的结果(聚合后的组) | | 执行时机 | 在 `GROUP BY` 之前执行 | 在 `GROUP BY` 之后执行 | | 是否可使用聚合函数 | ❌ 不可以(如 `COUNT`, `SUM` 等) | ✅ 可以 | | 通常与什么一起使用 | 普通列条件过滤 | 与 `GROUP BY` 聚合函数一起使用 | --- ### 🧩 示例说明 假设我们有一个销售表 `sales`: ```sql CREATE TABLE sales ( id SERIAL PRIMARY KEY, product VARCHAR(50), region VARCHAR(50), amount INT ); INSERT INTO sales (product, region, amount) VALUES ('A', 'North', 100), ('B', 'North', 150), ('A', 'South', 200), ('B', 'South', 50), ('A', 'North', 300); ``` #### ✅ 使用 `WHERE`:过滤原始行 你想查 **North 地区中每个产品的总销售额**,且只考虑金额大于 100 的记录: ```sql SELECT product, SUM(amount) AS total_amount FROM sales WHERE amount > 100 -- 过滤原始行,不能用聚合函数 GROUP BY product; ``` 👉 结果: - 只有 `amount > 100` 的行参与分组。 - 比如 `(A, North, 100)` 被排除。 --- #### ✅ 使用 `HAVING`:过滤分组结果 你想查 **每个地区总销售额超过 200 的地区**: ```sql SELECT region, SUM(amount) AS total_sales FROM sales GROUP BY region HAVING SUM(amount) > 200; -- 对分组后的聚合结果进行过滤 ``` 👉 结果: - 先按 `region` 分组并计算 `SUM(amount)` - 再筛选出总大于 200 的组 输出可能是: ``` region | total_sales --------+------------- North | 550 South | 250 ``` > 注意:这里 `SUM(amount)` 是一个聚合函数,只能在 `HAVING` 中使用,不能在 `WHERE` 中使用。 --- #### ❌ 错误示例:在 WHERE 中使用聚合函数 ```sql -- 错误!不能在 WHERE 中使用聚合函数 SELECT region, SUM(amount) FROM sales GROUP BY region WHERE SUM(amount) > 200; -- ❌ 报错:aggregate functions are not allowed in WHERE ``` --- ### 🔁 执行顺序回顾(SQL 查询逻辑顺序) 1. `FROM` 2. `WHERE` → 先过滤行 3. `GROUP BY` → 分组 4. `HAVING` → 过滤分组 5. `SELECT` → 计算选择的表达式 6. `ORDER BY` 7. `LIMIT` 所以: 👉 `WHERE` 影响的是“哪些行参与分组” 👉 `HAVING` 影响的是“哪些分组最终显示” --- ### ✅ 综合例子:同时使用 WHERE HAVING ```sql SELECT region, product, COUNT(*) AS count_items, SUM(amount) AS total_amount FROM sales WHERE amount > 50 -- 原始行过滤:只保留金额大于50的 GROUP BY region, product HAVING SUM(amount) > 200 -- 分组后过滤:总金额大于200的组才显示 ORDER BY total_amount DESC; ``` 解释: - `WHERE amount > 50`:先去掉所有 `amount <= 50` 的行(比如 `B, South, 50` 可能被去掉) - 然后按 `(region, product)` 分组统计 - 最后 `HAVING SUM(amount) > 200` 筛选出符合条件的分组 --- ### ✅ 小结 - **`WHERE`**:用来过滤“进入分组”的数据行,不能用聚合函数。 - **`HAVING`**:用来过滤“已经分组完成的结果”,可以使用聚合函数。 - 如果你需要基于“某个组的统计值”做判断(如“订单数大于5的客户”),就必须用 `HAVING`。 - 如果你只是想提前减少数据量(如“只看北京地区的用户”),就用 `WHERE`。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值