GROUPBY语句总结
GROUP BY语句从英⽂的字⾯意义上理解就是“根据(By)⼀定的规则进⾏分组(Group)”
作⽤是通过⼀定的规则将⼀个数据集划分成若⼲个⼩的区域,然后针对若⼲个⼩区域进⾏数据处理
在介绍GROUP BY语句之前,⾸先需要介绍和它关系密切的⼩伙伴——聚合函数
聚合函数四字祝福
——
聚合函数是对多值数据执⾏计算并返回单值的函数
以下是常⽤的聚合函数:
1. AVG——返回平均值,其中空值被忽略
例: lect dept_no, avg(sal) from table group by dept_no //统计不同部门的平均⼯资
支教总结2.COUNT——返回数量
例: lect count(name) from table //统计公司员⼯总数
count(字段名)与count(*)的区别:
如果字段名中包含空值NULL,那么count(字段名)会忽略该空值,⽽count(*)不会忽略,依然将其计⼊总数
例:
dept_1 dept_2
A D
B null
C E
由于dept_2 中有 null 值,⽤ count(dept_2) 的结果就是 2,⽤ count(*) 的结果就是 3
3. MAX——返回最⼤值
例: lect max(sal) from table //查找公司的最⾼⼯资
4. MIN——返回最⼤值
例: lect min(sal) from table //查找公司的最低⼯资
5.SUM——返回和
例: lect sum(sal) from table //统计公司⼯资总额
GROUP BY + [分组字段]
其中分组字段可以有多个。在执⾏了这个操作以后,数据集将根据分组字段的值将⼀个数据集划分成各个不同的⼩组。
⽐如有如下数据集(Table_Fruitinfo),其中⽔果名称(FruitName)和出产国家(ProductPlace)为联合主键:
Table_Fruitinfo
如果我们想知道每个国家有多少种⽔果,那么我们可以通过如下SQL语句来完成:
SELECT COUNT(*) AS ⽔果种类, ProductPlaceAS 出产国
FROM Table_Fruitinfo
GROUP BY ProductPlace
这句SQL语句可以解释成“我按照出产国家(ProductPlace)将数据集进⾏分组,然后分别统计各个国家的⽔果种类数”。
注意:如果我们这⾥⽔果种类不是⽤Count(*),⽽是类似如下写法的话:
SELECT FruitName, ProductPlace
FROM Table_Fruitinfo
GROUP BY ProductPlace
那么SQL在执⾏此语句的时候会报如下的类似错误:
诸葛亮与司马懿选择列表中的列'Table_Fruitinfo.FruitName'⽆效,因为该列没有包含在聚合函数或GROUPBY⼦句中
这就是我们需要注意的⼀点,使⽤GROUP BY语句时,返回集中的⾮聚合字段要么包含在Group By语句的后⾯,作为分组的依据;要使⽤GROUP BY语句时,返回集中的⾮聚合字段要么包含在Group By语句的后⾯,作为分组的依据;要么就要包含在聚合函数中。
我们可以将GROUP BY操作想象成如下的⼀个过程:
⾸先通过SELECT语句得到⼀个结果集,然后根据分组字段,将具有相同分组字段的记录归并成了⼀条记录。这时候那些不作为分组依据的字段就有可能出现多个值(⾮聚合字段),但是⼀种分组情况只能有⼀条记录,⽽⼀个数据格是⽆法放⼊多个数值的,所以就需要通过⼀定的处理(聚合函数)将这些多值的列转化成单值,然后放⼊对应的数据格中。
+ [分组字段]
GROUP BY ALL + [分组字段]
GROUP BY ALL
使⽤ ALL 关键字,即在不使⽤ ALL 关键字的情况下,包含 GROUP BY ⼦句的 SELECT 语句查找的结果只会显⽰满⾜搜索条件的记录。⽽使⽤ ALL 关键字,即使某些记录不满⾜搜索条件,查询结果也将显⽰ GROUP BY ⼦句⽣成的所有组,只是这些不满⾜搜索条件的记录不会进⾏真正的统计,⽽是
⽤默认值0或者NULL来代替聚合函数的返回值。说得有点绕,举个例⼦吧。
计,⽽是⽤默认值0或者NULL来代替聚合函数的返回值。
还是使⽤之前的⽔果信息数据集
Table_Fruitinfo
⾸先我们不使⽤带ALL关键字的Group By语句:
SELECT COUNT(*) AS ⽔果种类, ProductPlace AS 出产国
FROM Table_Fruitinfo
铸铁壶WHERE (ProductPlace <> 'Japan')
GROUP BY ProductPlace
操作符 <> 表⽰ “不等于”
那么在最后结果中由于Japan不符合where语句,所以分组结果中将不会出现Japan。
现在我们加⼊ALL关键字:
SELECT COUNT(*) AS ⽔果种类, ProductPlace AS 出产国
FROM Table_Fruitinfo
WHERE ( ProductPlace <> 'Japan')
GROUP BY ALL ProductPlace
重新运⾏后,我们可以看到Japan的分组,但是对应的“⽔果种类”不会进⾏真正的统计,聚合函数会根据返回值的类型⽤默认值0或者NULL来代替聚合函数的返回值。歌声嘹亮
WITH CUBE | ROLL UP
+ [分组字段] WITH CUBE | ROLL UP
GROUP BY + [分组字段]
GROUP BY
GROUP BY ALL语句不能和CUBE / ROLL UP关键字⼀起使⽤
所查找的维度
聚合函数。GROUP BY 后跟所查找的维度
所查找的维度列和聚合函数
CUBE 运算符在 SELECT 语句的 GROUP BY ⼦句中指定。SELECT语句后跟所查找的维度列
关键字 WITH CUBE
列和关键字 WITH CUBE
(笛卡尔积),以及与这些维度值组合相匹配的基础⾏中的聚合值
结果集包含维度列中各值的所有可能组合(笛卡尔积)
例:论报馆有益于国事
Inventory
高六以下查询将返回⼀个结果集,其中包含Item和Color的所有可能组合的Quantity⼩计:
SELECT Item, Color, SUM(Quantity) AS QtySum
FROM Inventory
GROUP BY Item, Color WITH CUBE
以下是结果集:
结果集
可以看到,CUBE将维度列Item和Color的所有可能属性(包括null)进⾏组合,形成了3*3=9条不同的记录,每条记录都包含着⼀个⼩计QtySum
但是,CUBE 操作⽣成空值将会带来⼀个问题:如何区分 CUBE 操作⽣成的 NULL 值和在实际数据中返回的 NULL 值?
GROUPING 函数解决此问题
可以使⽤ GROUPING 函数
如果列值来⾃真实数据(未知数据),GROUPING 函数将返回 0;如果列值是由 CUBE 操作⽣成的 NULL,则返回 1。
ALL
所有值,所以可以将CUBE操作⽣成的任⼀ NULL 替换为字符串 ALL
在 CUBE 操作中,⽣成的 NULL 代表所有值
UNKNOWN
真实数据中的 NULL 表⽰数据值未知
未知,所以可以将真实数据中的 NULL替换为字符串 UNKNOWN
SELECT CASE WHEN (GROUPING(Item) = 1) THEN 'ALL'
ELSE ISNULL(Item, 'UNKNOWN')
END AS Item,
CASE WHEN (GROUPING(Color) = 1) THEN 'ALL'
ELSE ISNULL(Color, 'UNKNOWN')
END AS Color,
SUM(Quantity) AS QtySum
FROM Inventory
GROUP BY Item, Color WITH CUBE
ISNULL:使⽤指定的替换值替换 NULL。
语法:ISNULL ( check_expression , replacement_value )
如果 check_expression 不为 NULL,那么返回该表达式的值;否则返回 replacement_value。
包含具有多个维度的 CUBE 的 SELECT 语句可⽣成⼤型结果集,因为这些语句会为所有维度中各值
安徽大学分数线
的所有组合都⽣成相应的⾏。这些⼤型结果集包含的数据可能会过多⽽不易于阅读和理解。此问题的⼀种解决办法是将SELECT语句放⼊视图(VIEW)中:
数据库中的数据都是存储在表中的,⽽视图只是⼀个或多个表依照某个条件组合⽽成的结果集
⼀般来说可以⽤UPDATE,INSERT,DELETE等sql语句修改表中的数据,⽽对视图只能进⾏SELECT操作
CREATE VIEW InvCube AS
SELECT CASE WHEN (GROUPING(Item) = 1) THEN 'ALL'
ELSE ISNULL(Item, 'UNKNOWN')
END AS Item,
CASE WHEN (GROUPING(Color) = 1) THEN 'ALL'
ELSE ISNULL(Color, 'UNKNOWN')