grouping sets函数

  • grouping sets: 根据不同的维度组合进行聚合,等价于将不同维度的group by结果集进行union all
  • grouping__id(请注意函数名中的下划线是两个!):表示结果属于哪一个分组集合,属于虚字段
  • cube: 根据group by的维度的所有组合进行聚合。
  • rollup: 为cube的子集,以最左侧的维度为主,从该维度进行层级聚合。(从右向左依次递减)

这几个分析函数通常用于,根据不同维度上钻和下钻的指标统计,比如,分小时、天、月的uv数
在一个group by查询中,根据不同的维度组合进行聚合,等价于将不同维度的group by结果集进行union all。
通俗的说,grouping sets是一种将多个group by 逻辑写在一个语句中的便利写法

上卷(roll-up):上卷是沿着维的层次向上聚集汇总数据。例如,对产品销售数据,沿着时间维上卷,可以求出所有产品在所有地区每月(或季度或年或全部)的销售额。
下探(drill-down):下探是上卷的逆操作,它是沿着维的层次向下,查看更详细的数据。
希望能帮助你理解。

数据:
10001	2007-12-24	2	A	1200
10005	2007-12-24	1	B	2000
10006	2008-01-18	1	C	1400
20001	2008-02-12	2	B	1200
20002	2009-02-16	1	C	2000
30001	2007-08-02	3	A	1000
30003	2009-04-18	2	B	1500
30004	2009-04-18	3	C	2200
30007	2009-09-07	3	D	3000
40001	2008-01-09	2	A	4000
40005	2009-02-12	3	A	1000
准备工作
create table orders(
    orderid int, 
    orderdate date, 
    empid int,    
    custid string,  
    qty int 
)
row format delimited fields terminated by '\t';

load data local inpath '/opt/module/hive/datas/Orders.txt' into table orders;

select*from orders;

在这里插入图片描述

– 1. 汇总每年收入

select
    year(orderdate) orderyear,
    sum(qty) sum_qty
from Orders
group by year(orderdate)
order by orderyear;

在这里插入图片描述

– 2. 公司每个月的收入

select
    year(orderdate) orderyear,
    month(orderdate) ordermonth,
    sum(qty) sum_qty
from Orders
group by year(orderdate),month(orderdate)
order by orderyear,ordermonth;

在这里插入图片描述

– 3. 公司收入(每年|每月)。1是按照年,2是按照年和月,汇总1、结果

-答案1

select
    year(orderdate) orderyear,
    null ordermonth,
    sum(qty) sum_qty
from Orders
group by year(orderdate)
union all
select
    year(orderdate) orderyear,
    month(orderdate) ordermonth,
    sum(qty) sum_qty
from Orders
group by year(orderdate),month(orderdate)
order by orderyear,ordermonth;

–null出现在里面按照年的汇总数据,非null为按照年和月的分组汇总
在这里插入图片描述

-答案2–用 GROUPING SETS实现相同结果

select
    year(orderdate) orderyear,
    month(orderdate) ordermonth,
    sum(qty) sum_qty,
    grouping__id  --表示结果属于哪一个分组集合,属于虚字段
from Orders
group by year(orderdate),month(orderdate) 
grouping sets ( year(orderdate),  --1st grouping set
                (year(orderdate), month(orderdate)) --2nd grouping set
                );

在这里插入图片描述

–等价于

select year(orderdate) orderyear,null,sum(qty) sum_qty,1 as grouping__id from Orders group by year(orderdate)           
union all          
select year(orderdate) orderyear,month(orderdate) ordermonth,sum(qty) sum_qty,0 as grouping__id from Orders group by year(orderdate),month(orderdate); 

–一个分组包含两个列,假设列A和B,两个列都需要包含在括号内:(column A, column B)。如果没有括号,这个子句将会被定义为独立的分组,结果就不同了。

select
    year(orderdate) orderyear,
    month(orderdate) ordermonth,
    sum(qty) sum_qty
from Orders
group by year(orderdate),month(orderdate) 
grouping sets (year(orderdate), month(orderdate) );

在这里插入图片描述

– 4. 加入总体汇总结果

select
    year(orderdate) orderyear,
    month(orderdate) ordermonth,
    sum(qty) sum_qty,
    grouping__id  
from Orders
group by year(orderdate),month(orderdate) 
grouping sets ( year(orderdate), (year(orderdate), month(orderdate)), () );

在这里插入图片描述

–为啥没2??

select
    year(orderdate) orderyear,
    month(orderdate) ordermonth,
    sum(qty) sum_qty,
   (case grouping__id when 1 then '年度' when 0 then '年度|月度' else '总' end)
from Orders
group by year(orderdate),month(orderdate) 
grouping sets ( year(orderdate), (year(orderdate), month(orderdate)), () );

在这里插入图片描述

1.在group by中使用rollup:

select
    empid,
    avg(qty)
from Orders
group by empid;

在这里插入图片描述

–rollup是cube的子集,以最左侧的维度为主,从该维度进行层级聚合
–在生成原有统计结果基础上,生成横向小计结果。

select
    nvl(empid, '所有订单平均') empid,
    avg(qty)
from Orders
group by rollup(empid);  --汇总的列返回的不是每个人的平均,而是所有行的平均(所有订单)

在这里插入图片描述

select
    nvl(empid, '所有订单平均') empid,
    custid,
    avg(qty)
from Orders
group by rollup(empid, custid);  

在这里插入图片描述

这里如果是group by rollup(a,b,c);对(a,b,c)三列分组的话,就是先对(a,b,c)进行group by,再对(a,b)进行group by,再对(a)进行group by,再对全表group by。从右向左依次递减

即rollup(1,2…n)时,group by的所有可能的group by数是n+1个,比如rollup(a,b,c);时,总共有4个汇总。

2.在group by中使用cube:

–cube操作符时,在生成原有统计结果基础上,生成纵向小计结果。
–根据GROUP BY的维度的所有组合进行聚合

select
    empid,
    avg(qty)
from Orders
group by cube(empid);

在这里插入图片描述

select
    nvl(empid, '订单平均') empid,
    custid,
    avg(qty)
from Orders
group by cube(empid, custid);

在这里插入图片描述

–另一种写法

select
    month(orderdate) ordermonth,
    day(orderdate) orderday,
    sum(qty) sum_qty,
    grouping__id
from Orders
group by orderdate
with cube
order by grouping__id;

在这里插入图片描述

如果是group by cube(a,b,c);首先会对(a、b、c)进行group by,然后依次是(a、b),(a、c),(a),(b、c),(b),©,再对全表进行group by。

即cube(1,2,n)时,group by的所有可能的group by数是2的n次方,比如cube(a,b,c);时,总共有8个。

总结:rollup非常高效,对一个查询增加的开销非常少;cube相对更耗费资源。
在group by子句有列(a,b)两列时,rollup统计(a,b),(a);而cube统计了(a,b),(a),(b)。

4.grouping函数,区分出小计,汇总数据,只能在使用rollup或cube的查询中使用。

–对输入列返回0或1,如果该行数据使用了数据的列中的信息,即此列数据参与rollup/cube函数分组汇总活动,则输出0;没有用到则输出1

select
    nvl(empid, '订单平均') empid,
    custid,
    avg(qty),
    grouping(empid) g_e,
    grouping(custid) g_c
from orders
group by rollup(empid, custid);

在这里插入图片描述
–通过在 having 子句中使用 grouping 函数,您可以只显示 empid 和 custid 组合的小计。

select
    nvl(empid, '订单平均') empid,
    custid,
    avg(qty),
    grouping(empid) g_e,
    grouping(custid) g_c
from orders
group by rollup(empid, custid)
having grouping(custid) = 0;

在这里插入图片描述

–注意:有些表有一项由于表达式所基于的列对于表中的一行或多行为 null 值而返回 null 值,而不是表示该列的小计(此null非分组null)

5.grouping__id函数

–grouping__id 函数返回一个整数值。该值对应于位向量的十进制解释,该向量由串联的 1 和 0 组成,将由一系列 grouping 函数按从左到右的顺序返回,这与 grouping__id 函数中指定参数的顺序相同。二进制

select
    nvl(empid, '订单平均') empid,
    custid,
    avg(qty),
    grouping__id
from orders
group by empid,custid 
grouping sets(empid, custid);

在这里插入图片描述

select
    nvl(empid, '订单平均') empid,
    custid,
    avg(qty),
    if(grouping__id = 1, '员工平均', '顾客平均')
from orders
group by empid,custid 
grouping sets(empid, custid);

在这里插入图片描述

–二进制

select
    year(orderdate) orderyear,
    month(orderdate) ordermonth,
    sum(qty) sum_qty,
    grouping(year(orderdate)) g_y,
    grouping(year(orderdate), month(orderdate)) g_ym,
    grouping__id gid 
from Orders
group by year(orderdate),month(orderdate) 
grouping sets ( year(orderdate), (year(orderdate), month(orderdate)), () );

在这里插入图片描述

–好理解

select
    nvl(empid, '订单平均') empid,
    custid,
    avg(qty),
    grouping(empid) g_e,
    grouping(custid) g_c,
    grouping__id gid
from orders
group by empid,custid 
grouping sets(empid, custid);

–在hive里grouping__id不能放参数,oral可以
在这里插入图片描述

6.grouping__sets多维度组合去重统计避免使用distinct

–通过grouping sets和distinct进行统计

select
    grouping__id g_id,
    year(orderdate) orderyear,
    month(orderdate) ordermonth,
    sum(qty) sum_qty,
   count(distinct empid) dis_empid
from Orders
group by year(orderdate),month(orderdate) 
grouping sets ( year(orderdate),  
                (year(orderdate), month(orderdate)) 
                );

在这里插入图片描述

–通过grouping sets将empid加入维度组合再进行group by统计

select g_id, orderyear, ordermonth, sum(sum_qty), count(1) dis_empid
  from 
  (
    select
        cast(grouping__id as int)&7 g_id,--可以让grouping__id好看点
        year(orderdate) orderyear,
        month(orderdate) ordermonth,
        sum(qty) sum_qty,
        empid
    from Orders
    group by year(orderdate),month(orderdate),empid 
    grouping sets ( (year(orderdate),empid),  
                (year(orderdate), month(orderdate),empid) 
                )
  ) t
 group by g_id, orderyear, ordermonth;  

在这里插入图片描述

–在hive没有group by all----sql或olap有

select
    empid,
    sum(qty) sum_qty
from orders
where empid=2
group by all empid;

hive grouping sets多维度报错

如果你的 grouping sets大于等于5个维度,将会报如上的错误;解决办法:

An additional MR job is introduced since the cardinality of grouping sets is more than hive.new.job.grouping.set.cardinality. This functionality is not supported with distincts. Either set hive.new.job.grouping.set.cardinality to a high number (higher than the number of rows per input row due to grouping sets in the query), or rewrite the query to not use distincts. The number of rows per input row due to grouping sets is 32
  1. 在你的hql语句前面加上 set hive.new.job.grouping.set.cardinality=xx;(例如我这里是5个维度,一共32个grouping sets,xx我写的64 )
  2. 可以通过在子查询中用group by去重,避免在聚合中用到distinct

hive中grouping sets 数量较多时,可以使用如下设置来:set hive.new.job.grouping.set.cardinality = 30;这条设置的意义在于告知解释器,group by之前,每条数据复制量在30份以内。

当维度过高,且统计语句中使用了 count distinct语句,就有可能出现如下报错

- Error while compiling statement: FAILED: SemanticException [Error 10226]: An additional MR job is introduced since the cardinality of grouping sets is more than hive.new.job.grouping.set.cardinality. This functionality is not supported with distincts. Either set hive.new.job.grouping.set.cardinality to a high number (higher than the number of rows per input row due to grouping sets in the query), or rewrite the query to not use distincts. The number of rows per input row due to grouping sets is 256

此时可以通过以下语句突破这个限制set hive.new.job.grouping.set.cardinality = 256;

其中256 为可以调节的数字,一般这个数字要大于你的维度的最高值,但是切记要慎用,一般维度最好不要超过7维,否则对集群压力会比较大

  • 6
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
注:分二卷,点击上传者查看第二卷地址。亲,本人纯手工添加了书签哦!!方便阅读 《Microsoft SQL Server 2008技术内幕:T-SQL查询》全面深入地介绍了Microsoft SQL Server 2008中高级T-SQL查询、性能优化等方面的内容,以及SQL Server 2008新增加的一些特性。主要内容包括SQL的基础理论、查询优化、查询算法及复杂度,以及在使用子查询、表表达式、排名函数、数据聚合和透视转换、TOP和APPLY、数据修改、分区表、特殊数据结构等实际应用时会遇到的各种高级查询问题和解决方案。   作为一本讲述T-SQL高级查询的专业图书,《Microsoft SQL Server 2008技术内幕:T-SQL查询》旨在结合实践中的各种常见问题,教读者如何用SQL作为语言工具来思考问题,揭示基于集合查询的强大威力。《Microsoft SQL Server 2008技术内幕:T-SQL查询》内容丰富、文字简洁明快,列举的实例具有一定的难度,而且实用性很强,可以把它们作为解决实际问题的标准模式。阅读《Microsoft SQL Server 2008技术内幕:T-SQL查询》,可以充分地理解T-SQL语言和良好的编程实践,学会如何编写更加有效而强大的查询语句。 序言 I 致谢III 前言 V 第1章 逻辑查询处理 1.1 逻辑查询处理的各个阶段 1.1.1 逻辑查询处理阶段简介 1.2 客户/订单场景下的查询示例 1.3 逻辑查询处理阶段详解 1.3.1 步骤1:FROM阶段 1.3.2 步骤2:WHERE阶段 1.3.3 步骤3:GROUP BY阶段 1.3.4 步骤4:HAVING阶段 1.3.5 步骤5:SELECT阶段 1.3.6 步骤6:排序用的ORDER BY阶段 1.4 逻辑查询处理的深入内容 1.4.1 表运算符 1.4.2 OVER子句 1.4.3 集合运算符 1.5 总结 第2章 集合论和谓词逻辑 2.1 自然语言表述到数学表示的转换 2.1.1 严格定义(well-Definedness) 2.1.2 相等、恒等和同一性 2.1.3 数学命名约定 2.1.4 数字 2.1.5 上下文 2.1.6 函数、参数和变量 2.1.7 指令和算法 2.2 集合论 2.2.1 集合的标记方法 2.2.2 集合的严格定义 2.2.3 论域 2.2.4 真实性 2.2.5 罗素悖论(Russell s Paradox) 2.2.6 有序对、元组和笛卡尔积 2.2.7 空集 2.2.8 集合的特征函数 2.2.9 集合的基数(Cardinality) 2.2.10 顺序 2.2.11 集合运算符 2.2.12 集合论的推广 2.3 谓词逻辑 2.3.1 编程语言中的逻辑功能 2.3.2 命题和谓词 2.3.3 排中律 2.3.4 与、或、非运算 2.3.5 逻辑等价 2.3.6 逻辑蕴含 2.3.7 量化(Quantification) 2.3.8 替代和推广 2.4 关系 2.4.1 自反性、对称性和传递性 2.5 一个实际的应用 2.6 总结 第3章 关系模型 3.1 关系模型简介 3.1.1 关系、元组和类型 3.1.2 关系模型:快速摘要 3.2 关系代数和关系计算 3.2.1 基本运算符 3.2.2 关系代数 3.2.3 Codd提出的8个原始关系运算符 3.2.4 关系演算 T-SQL支持 3.3 数据完整性 3.3.1 声明式约束 3.3.2 实施完整性的其他方法 3.4 数据库正规化和其他设计主题 3.4.1 解决函数依赖的范式 3.4.2 更高级的范式 3.4.3 反规范化(Denormalization) 3.4.4 一般化和特殊化 3.5 总结 第4章 查询优化 4.1 本章用到的样本数据 4.2 优化方法论 4.2.1 分析实例级别的等待 4.2.2 关联等待和队列 4.2.3 确定行动方案 4.2.4 细化到数据库/文件级别 4.2.5 细化到进程级别 4.2.6 优化索引和查询 4.3 查询优化的工具  4.3.1 查询执行计划的缓存  4.3.2 清空缓存 4.3.3 动态管理对象 4.3.4 STATISTICS 4.3.5 测量查询的运行时间 4.3.6 分析执行计划 4.3.7 图形化的执行计划 4.3.8 提示(Hint) 4.3.9 跟踪/Profiler 4.3.10 数据库引擎优化顾问 4.3.11 数据收集和管理数据仓库 4.3.12 使用SMO来复制统计信息 4.4 索引优化 4.4.1 表和索引的结构 4.4.2 索引访问方法 4.4.3 索引策略的分析 4.4.4 碎片 4.4.5 分区 4.5 准备样本数据 4.5.1 数据准备 4.5.2 TABLESAMPLE2 4.6 基于集合的方法和迭代/过程方法的比较,以及一个优化练习2 4.7 总结 第5章 算法和复杂性 5.1 你有一个1夸特的硬币吗? 5.1.1 如何从零钱罐中取回1夸特钱 5.1.2 有时零钱罐中没有1夸特的硬币 5.2 如何度量算法(How Algorithms Scale) 5.2.1 二次缩放(Quadratic Scaling)的一个例子 5.2.2 具有线性复杂度的算法 5.2.3 指数和超指数复杂度 5.2.4 次线性(sublinear)复杂度 5.2.5 常量复杂度 5.2.6 复杂度的技术定义 5.2.7 复杂度的比较 5.3 经典算法和算法策略 5.3.1 排序算法 5.3.2 字符串查找 5.4 一个实际的应用程序 5.4.1 识别测量数据的趋势 5.4.2 LISLP算法的复杂度 5.4.3 用T-SQL解决最长上升子序列的长度问题 5.5 总结 第6章 子查询、表表达式和排名函数 6.1 子查询 6.1.1 独立子查询 6.1.2 相关子查询 6.1.3 行为不当的子查询 6.1.4 不常用的谓词 6.2 表表达式(Table Expressions) 6.2.1 派生表 6.2.2 公用表表达式 6.3 分析排名函数 6.3.1 行号 6.3.2 排名和密集排名(Dense Rank) 6.3.3 组号(Tile Number) 6.4 数字辅助表 6.5 缺失范围和现有范围(也称为间断和孤岛) 6.5.1 缺失范围(间断) 6.5.2 现有范围(孤岛) 6.6 总结 第7章 联接和集合运算 7.1 联接 7.1.1 旧语法和新语法 7.1.2 基本联接类型 7.1.3 其他的联接分类 7.1.4 上一年度的滑动合计 7.1.5 联接算法 7.1.6 拆分元素 7.2 集合运算 7.2.1 UNION 7.2.2 EXCEPT  7.2.3 INTERSECT 7.2.4 集合运算的优先级 7.2.5 在集合运算中使用INTO 7.2.6 避开不支持的逻辑阶段 7.3 总结 第8章 数据聚合和透视 8.1 OVER 子句 8.2 决胜属性(Tiebreaker) 8.3 连续聚合 8.3.1 累积聚合(Cumulative Aggregation) 8.3.2 滑动聚合(Sliding Aggregation) 8.3.3 年初至今(YTD) 8.4 透视转换(Pivoting)35 8.4.1 透视转换属性35 8.4.2 关系除法 8.4.3 聚合数据 8.5 逆透视转换 8.6 自定义聚合 8.6.1 使用透视转换的自定义聚合 8.6.2 用户定义聚合函数(UDA,User Defined Aggregate) 8.6.3 专用解决方案 8.7 直方图(Histogram) 8.8 分组因子 8.9 分组集 8.9.1 样例数据 8.9.2 GROUPING SETS从属子句 8.9.3 CUBE从属子句 8.9.4 ROLLUP从属子句 8.9.5 分组集代数 8.9.6 GROUPING_ID函数 8.9.7 保存分组集 8.9.8 排序 8.10 总结 第9章 TOP和APPLY 9.1 SELECT TOP 9.1.1 TOP和确定性 9.1.2 TOP和输入表达式 9.1.3 TOP和修改 9.1.4 增强的TOP 9.2 APPLY 9.3 使用TOP和APPLY解决常见问题 9.3.1 每组中的TOP n 9.3.2 匹配当前值和前一个值 9.3.3 分页 9.4 逻辑转换 9.5 总结 第10章 数据修改 10.1 插入数据 10.1.1 增强的VALUES子句 10.1.2 SELECT INTO 10.1.3 BULK行集提供程序 10.1.4 按最小方式记录日志的操作  10.1.5 INSERT EXEC 10.1.6 序列机制45 10.2 删除数据 10.2.1 TRUNCATE与DELETE 10.2.2 删除包含重复数据的行 10.2.3 基于联结的DELETE 10.3 更新数据 10.3.1 基于联结的UPDATE 10.3.3 更新大值数据类型 10.3.3 用SELECT和UPDATE语句进行赋值 10.4 合并数据 10.4.1 MERGE语句基础 10.4.2 额外增加一个谓词 10.4.3 多个WHEN子句 10.4.4 WHEN NOT MATCHED BY SOURCE子句 10.4.5 MERGE Values 10.4.6 MERGE与触发器 10.5 OUTPUT子句 10.6 总结 第11章 查询分区表 11.1 在SQL Server中进行分区 11.1.1 分区视图 11.1.2 分区表 11.2 总结 第12章 图、树、层次结构和递归查询 12.1 术语 12.1.1 图 12.1.2 树 12.1.3 层次结构 12.2 应用场景 12.2.1 员工组织图 12.2.2 材料清单(BOM) 12.2.3 道路系统 12.3 迭代/递归 12.3.1 下属 12.3.2 祖先 12.3.3 带有路径枚举的子图/子树 12.3.4 排序 12.3.5 环 12.4 具体化路径 12.4.1 维护数据 12.4.2 查询 12.5 使用HIERARCHYID数据类型的具体化路径5 12.5.1 维护数据 12.5.2 查询 12.5.3 使用HIERARCHYID的其他方面 12.6 嵌套集合 12.6.1 分配左值和右值 12.6.2 查询 12.7 传递闭包(Transitive Closure) 12.7.1 有向无环图 12.7.2 无向有环图 12.8 总结 索引

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值