您的位置:首页 > 数据库

【SQL】分组数据,过滤分组-group by , having

2014-05-01 23:13 459 查看

创建分组 - GROUP BY

分组是在SELECT语句的GROUP BY子句中建立的。它的作用是通过一定的规则将一个数据集划分成若干个小的区域,然后针对若干个小区域进行数据处理SELECT子句中的列名必须为分组列或列函数,列函数对于GROUP BY子句定义的每个组各返回一个结果

一些规定:

GROUP BY 子句可以包含任意数目的列,这使得能对分组进行嵌套,为数据分组提供更细致的控制;
如果在GROUP BY子句中嵌套了分组,数据将在最后规定的分组上进行汇总;
GROUP BY子句中列出的每个列都必须是检索列或有效的表达式。如果在SELECT中使用表达式,则必须在GROUP BU子句中指定相同的表达式,不能使用别名;
大多数SQL实现不允许GROUP BU列带有长度可变的数据类型(如文本或备select departmentid, departmentname from basicdepartment group by departmentid;注型字段);
除聚集计算语句外,SELECT语句中的每个列都必须在GROUP BY子句中给出
如果分组列中具有NULL值,则NULL将作为一个分组返回。如果列中有多行NULL值,它们将分为一组;
GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前;

示例:

<span style="font-family:SimSun;font-size:10px;">select departmentid, count(*) as 'number' from basicdepartment group by departmentid;</span>
departmentid将数据集进行了分组,然后再进行各个组的统计数据分别有多少。

如果不用count(*)而用类似下面的语法:

<span style="font-family:SimSun;font-size:10px;">select departmentid, departmentname from basicdepartment group by departmentid;</span>
将会出现错误,选择列表中的departmentname无效,因为该列没有包含在聚合函数或者GROUP BY子句中。

注意:如果在返回集字段中,这些字段要么就要包含在GROUP BY语句的后面,作为分组的依据;要么就要被包含在聚合函数中

过滤分组 - HAVING

除了能用GROUP BY分组数据外,SQL还允许过滤分组,规定包括哪些分组,排除哪些分组。例如,可能想要列出至少有两个订单的所有顾客,为了得出这种数据,必须基于完整的分组而不是个别的行进行过滤。

WHERE过滤行,而HAVING过滤分组HAVING支持所有WHERE操作符,HAVING子句中能使用聚集函数WHERE在数据分组前进行过滤。HAVING在数据分组后进行过滤。WHERE排除的行不包括在分组中

示例:

select cust_id, count(*) as orders from Orders group by cust_id having count(*) >= 2;


分组 V.S. 排序 - GROUP BY V.S. ORDER BY

ORDER BYGROUP BY
排序产生的输出分组行,但输出可能不是分组的顺序
任意列都可以使用只可能使用选择列或表达式列,而且必须使用每个选择列表达式
不一定需要如果与聚集函数一起使用列,则必须使用
千万不要仅依赖GROUP BY排序数据。

示例

下表:学生号(SNO),课程名(PNO),成绩(GRADE)

1 YY
90

1 SX 98

1 YW 95

2 YY 92

2 SX 91

2 YW 89

3 YY 96

3 SX 88

3 YW 85

4 YY 88

4 SX 89

4 YW 95

1. 显式90分以上学生的课程名和成绩

select * from sc where GRADE >= 90


4 YW
95

3 YY 96

2 YY 92

2 SX 91

1 YY 90

1 SX 98

1 YW 95

2. 显式每个学生的成绩在90分以上的各有多少门

select SNO, count(*) from sc where GRADE >= 90 group by SNO


1 3

2 2

3 1

4 1

3. 至少有两门课程在90分以上的学生号及90分以上的课程数 (过滤分组)

select SNO, count(*) from sc where GRADE >= 90 group by SNO having count(*) >= 2


1 3

2 2

4. 选出平均成绩大于90分,且语文必须在95以上的学生

select SNO, avg(GRADE) from sc where SNO in (select SNO from sc where PNO = 'YW' and GRADE >= 95) group by SNO having avg(GRADE) >= 90


1 94.333336

4 90.666664

***应用***

股票order表 t_order_fidessa_his :

order_id order_qty symbol ex_destination

00001768627ORHK1
6000 933
HK

00001768632ORHK1
1200 933
HK

00001768634ORHK1
2000 941
HK

00001768634ORHK1
6000 941
HK

00001768634ORHK1
6000 941
HK

00001768634ORHK1
7000 941
HK

查询,同一symbol 是否存在不同的ex_destination值:

select temp.symbol, count(*) from
(select t.symbol as symbol, t.ex_destination as ex_destination from t_order_fidessa_his t group by t.symbol, t.ex_destination) temp
group by temp.symbol having count(*) > 1


通过两次group by 查询。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: