SQL学习之Group by和Having

转自:http://dev.yesky.com/230/2669730.shtml

  在介绍GROUP BY 和 HAVING 子句前,我们必需先讲讲sql语言中一种特殊的函数:聚合函数,例如SUM, COUNT, MAX, AVG等。这些函数和其它函数的根本区别就是它们一般作用在多条记录上。

SELECT SUM(population) FROM bbc

  这里的SUM作用在所有返回记录的population字段上,结果就是该查询只返回一个结果,即所有国家的总人口数。

  通过使用GROUP BY 子句,可以让SUM 和 COUNT 这些函数对属于一组的数据起作用。当你指定 GROUP BY region 时, 属于同一个region(地区)的一组数据将只能返回一行值,也就是说,表中所有除region(地区)外的字段,只能通过 SUM, COUNT等聚合函数运算后返回一个值。

  HAVING子句可以让我们筛选成组后的各组数据,WHERE子句在聚合前先筛选记录.也就是说作用在GROUP BY 子句和HAVING子句前.
而 HAVING子句在聚合后对组记录进行筛选。

  让我们还是通过具体的实例来理解GROUP BY 和 HAVING 子句,还采用第三节介绍的bbc表。

  SQL实例:

  一、显示每个地区的总人口数和总面积:

SELECT region, SUM(population), SUM(area)
FROM bbc
GROUP BY region

  先以region把返回记录分成多个组,这就是GROUP BY的字面含义。分完组后,然后用聚合函数对每组中的不同字段(一或多条记录)作运算。

  二、 显示每个地区的总人口数和总面积.仅显示那些面积超过1000000的地区。

SELECT region, SUM(population), SUM(area)
FROM bbc
GROUP BY region
HAVING SUM(area)>1000000

  在这里,我们不能用where来筛选超过1000000的地区,因为表中不存在这样一条记录。

  相反,HAVING子句可以让我们筛选成组后的各组数据.  
### SQLGROUP BYHAVING的区别与使用场景 #### GROUP BY的作用 `GROUP BY` 是用于将数据按照指定的一个或多个字段进行分组的关键字。通过 `GROUP BY`,可以对每组内的数据执行聚合操作(如求、计数、最大值等),从而实现更复杂的查询逻辑。例如,在销售数据表中按产品类别分组并计算总销售额: ```sql SELECT product_category, SUM(sale_amount) AS total_sales FROM sales GROUP BY product_category; ``` 此语句会返回每个产品的类别及其对应的总销售额[^1]。 当涉及多列分组时,可以通过在 `GROUP BY` 子句中列举多个字段来完成复杂分组。例如,如果需要按年份地区两层维度统计销售额,则可写成如下形式: ```sql SELECT year, region, COUNT(*) AS order_count FROM orders GROUP BY year, region; ``` 这表示先依据订单发生的年份再进一步细分到地区层次上做汇总处理[^2]。 #### HAVING的作用 虽然 `WHERE` 可以用来设置筛选条件,但它仅适用于未被分组前的原始记录集;而一旦引入了 `GROUP BY` 对数据进行了分组之后,若还需要基于这些分组的结果施加额外约束,则需要用到 `HAVING` 子句。换句话说,`HAVING` 主要针对的是经过聚合运算后的结果实施过滤。 比如,为了找到那些至少有四位成员参与评分的商品种类,我们可以这样编写SQL语句: ```sql SELECT category_id, AVG(price) AS average_price FROM dw_goods GROUP BY category_id HAVING AVG(price) > 100 AND COUNT(*) >= 4; ``` 这里尝试错误地把别名作为判断标准(`ag>100`)将会引发异常提示:“Unknown column 'ag' in 'where clause'”,因为别名无法直接应用于 `WHERE` 中,但可以在 `HAVING` 部分正常工作[^3]。 另外一个重要例子就是找出修读超过三门课并且成绩均合格的同学名单: ```sql SELECT Sno FROM SC WHERE Grade >= 60 GROUP BY Sno HAVING COUNT(DISTINCT Cno) >= 3; ``` 上述代码片段展示了如何利用 `WHERE` 排除不合格分数后再借助 `HAVING` 剔除非目标群体学生的信息[^4]。 #### 使用场景对比分析 | 功能描述 | 关键词 | 应用范围 | |----------|--------------|------------------------------------------------------------------------| | 数据预筛 | **WHERE** | 在任何情况下都可以单独使用的初步过滤工具 | | 聚合后滤 | **HAVING** | 当存在 `GROUP BY` 并希望根据分组统计数据设定附加限制条件下才需调用 | 总结来说,`WHERE` 更适合于单条记录级别的简单条件匹配任务,而面对涉及到整体趋势或者特定群体现象的研究课题时,就需要依赖 `GROUP BY` 结合 `HAVING` 来达成目的[^5]。 ### 示例代码展示 以下是综合运用 `GROUP BY` `HAVING` 的实例: 假设有一个名为 `employees` 的表格存储着雇员姓名 (`name`)、所属部门编号 (`department_id`)以及薪资水平 (`salary`) ,现在想要知道哪些部门拥有不少于两位年薪高于五万美金的职员? ```sql SELECT department_id, COUNT(name) AS high_salary_employees_num FROM employees WHERE salary > 50000 GROUP BY department_id HAVING COUNT(name) >= 2; ``` 这段脚本首先限定只考虑高薪人员,接着按部门整理他们的数量最后保留满足最低人数规定的组合列表。 --- 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值