京公网安备 11010802034615号
经营许可证编号:京B2-20210330
【每周一期-数据蒋堂】SQL的有序分组
我们知道,SQL延用了数学上的无序集合概念,所以SQL的分组并不关注过待分组集合中成员的次序。我们在前面讨论过的等值分组和非等值分组,也都没有关注过这个问题,分组规则都是建立在成员取值本身上。但如果我们要拓展SQL,以有序集合为考虑对象时,那就必须考虑成员次序对分组的影响了,而且,现实业务中有大量的有序分组应用场景。
一个简单的例子:将一个班的学生平均分成三份(假定人数能被3整除)。按我们在前面所说的分组定义,这也可以看成是一种分组,但这个运算在SQL中却很难写出来,因为分组依据和成员取值没有关系。
如果使用我们在前面讲有序遍历语法时的#符号,这个问题就很容易解决了。
A.group( (#-1)*3\A.len() ) // 按序号分成前1/3,中1/3,后1/3
A.group( (#-1)%3 ) // 还可以按序号每三个中取一个构成分组子集
用SQL实现这个运算就麻烦很多,需要先用子查询造出一个序号,然后再执行类似的分组规则。
上面这个例子中其实还没有真正关注成员的次序,只是说明了序号的作用,待分组集合的成员是其它次序时也可以得到可用的结果。
我们再看更多例子。
处理文本日志时,有些日志的基本单位不是1行,而可能是3行,即每个事件总是写出3行文本,这并不是多罕见的情况。对付这种日志时,就需要把文本每3行拆成一个分组子集,然后针对每个分组再进行详细的分析处理。这时要正确的分组运算就必须依赖于待分组集合中成员(文本日志的行)的次序了。
入学考试之后,把学生按成绩排序蛇行分拆成两个班,即名次1,4,5,8,...在一个,而2,3,6,7,...在另一个班,这样能保证两个班的平均名次是相同的。这个分组也可以用序号做出来:
A.sort@z(score).group(#%4<2)
这里用的分组值不再是常见的普通数值,而是一个布尔量,相当于按“真“值和“假”值分成两个组,真值对应第一个班,假值对应另一个班。本质上讲,这还是个等值分组,只是用到的分组值可以是任意泛型。
显然,这个分组的正确性也严重依赖于待分组集成的成员次序。
顺便说一句,这又是一个只关注分组子集而不关心聚合值的例子。按序号分组在很多情况下就是用序号来计算出分组依据,然后就变成普通的等值分组了。那么有没有不能简单地转换成等值分组的情况呢?
有一组婴儿出生记录,是按出生次序排序的,我们现在关心连续出生的同性别婴儿数量超过5的有多少批?
简单想,这就是先GROUP,计算每组COUNT值,然后数出有几个大于5的。后两步很简单,问题是怎么GROUP?
直接按婴儿性别分组当然是不对的,必须考虑次序,依次扫描记录,当婴儿性别发生变化时则产生一个新组。这种分组显然没法直接用等值分组做出来了。
我们可以提供一个有序分组方法来实现这种分组:当考察值发生变化时就产生一个新的分组。
A.group@o(gender).count(~.len()>5) // @o选项表示分组值变化时将产生新分组。
用SQL就麻烦很多,需要先造成中间标志和变量来生成组的序号,大概是这样
SELECT COUNT(*) FROM
(SELECT ChangeNumber FROM
(SELECT SUM(ChangeFlag) OVER (ORDER BY birthday) ChangeNumber FROM
(SELECT CASE WHEN gender=LAG(gender) OVER ( ORDER BY birthday) THEN 0 ELSE 1 END ChangeFlag FROM A))
GROUP ChangeNumber HAVING COUNT(*)>5)
这样的SQL,看懂都不是很容易的。而且必须借助birthday这种字段来形成次序,而前述的有序分组写法在原数据有序时根本用不着这个信息。
这种场景同样可能出现在文本分析中。每个用户的事件日志可能多行,而且行数不确定,但写日志时会在每个行开始处写上用户号。这样我们可以按这个用户号进行有序分组,它变化时就说明是另一个用户的事件了。
即使是普通的等值分组,如果事先知道原集合对分组字段有序,也可以使用这种方案来实施,这将获得更高的性能,比数据库常用的HASH分组方案要快得多,而且特别适合大数据遍历的情况。
再看一个著名的问题:一支股票最长连续上涨了多少天?
这个问题当然可以直接遍历去解决,不过我们现在用分组的思路来处理,至少在SQL体系下只能这么做(严格些说,这是目前找到的最简单可行的办法)。
将股票收盘价按日期排序,然后将连续上涨的日期分到同一组,这样只要考虑哪一组成员数最多即可。更明确地说,就是当某天上涨了,就把这一天和前一天分到一个组中,某天下跌了,则产生一个新组。
用SQL实现这个思路,同样需要用中间标志和变量来生成组序号:
SELECT MAX(ContinuousDays) FROM
(SELECT COUNT(*) ContinuousDays FROM
(SELECT SUM(RisingFlag) OVER (ORDER BY TradingDate ) NoRisingDays FROM
(SELECT TradingDate,
CASE WHEN ClosingPrice>LAG(ClosingPrice) OVER (ORDER BY TradingDate THEN 0 ELSE 1 END) RisingFlag
FROM A))
GROUP BY NoRisingDays)
如果有专门的有序分组方法以及以前说过的有序遍历语法,这个运算就很简单了:
A.sort(TradingDate).group@i(ClosingPrice
与SQL不同,虽然实现思路完全一样,但写出来是分步的,而不是一个多层嵌套语句,书写和理解都要容易得多。
同样地,这种场景也会在文本分析中有用。不确定行数的日志中,有时会在事件分始时写一个标志串,当扫描到这个标志串的时候就产生一个新的分组,有序分析的条件可设定为当前扫描行和指定文字相同,这样就能保证同一事件的日志信息在同一个组中。
后两种有序分组的情况,理论上当然也可以转换成等值分组来处理(用SQL就要这么做,这也能从另一个侧面说明SQL运算体系的完备性),但确实是相当麻烦的,所以我们一般不把它再当成等值分组来处理了。
到目前为止的分组讨论,都是假定待分组集合已经准备好,其成员可以被随机访问到。但如果数据量巨大而不能全部读入时,如果继续做这种假定,会导致频繁的外存交换而性能极差,这时需要再设计以流方式边读入边分组并且边聚合的运算体系。事实上日志分析中更常见的是这种情况,这些问题我们将再撰文研究,但基本方法思路仍然离不开上面这些内容。
数据分析咨询请扫描二维码
若不方便扫码,搜微信号:CDAshujufenxi
CDA数据分析师 出品 作者:李诗怡 四层结构 · 零件与房子 · 六大易错点 一、什么是指标体系 定义:指标体系是整套完整框架 ...
2026-10-13写在开头 先还原一个你大概率见过的场面。 立项会上有人说:我们得做用户画像。 于是团队关进会议室,白板写满便利贴,两小时后 ...
2026-10-13 很多数据分析师每天都在计算指标、制作报表,但当被问到“什么叫指标数据元”“指标数据标准包含哪些核心维度”“指标数据质 ...
2026-10-13在统计学与数据分析研究中,相关性分析分为数值变量分析与分类变量分析两大类。针对身高、销量、分数等连续数值变量,通常采用皮 ...
2026-10-12在Power BI可视化分析体系中,常规表格仅能展示枯燥的数值数据,存在数据对比不直观、强弱规律不突出、维度交叉分析低效等问题。 ...
2026-10-12 很多数据分析师能熟练写SQL、做透视表,但当被问到“数据是从哪里来的?经过哪些加工才进入数据仓库?ETL具体做了什么?”时 ...
2026-10-12在传统零售行业同质化竞争激烈、大众营销转化率持续走低的背景下,依托经验与直觉的粗放式营销逐渐失效。美国塔吉特百货(Target ...
2026-10-10随着智能客服、数字化服务、用户精细化运营的快速普及,传统零散、非标准化的客户服务数据与业务体系逐渐难以支撑高效服务治理。 ...
2026-10-10 很多数据分析师能熟练地写SQL、做透视表、算描述性统计,但当被问到“如何预测用户流失概率”“如何归因销量下滑的关键因素 ...
2026-10-10CDA数据分析师 出品 作者:李诗怡 定义区别 · 场景举例 · 指标分类 · 计算方法 知识体系总览 模块 包含内容 一、核 ...
2026-10-09在数据分析工作流中,业务数据大多存储在各类关系型数据库内,例如MySQL、PostgreSQL、SQLite等。Pandas是Python生态中主流的数 ...
2026-10-09在数字化精细化运营时代,海量用户存在需求差异、行为差异、价值差异与偏好差异。如果企业采用“一刀切”的统一营销、统一服务、 ...
2026-10-09 很多数据分析师拿到数据就开始清洗、建模,但当被问到“这批数据属于什么类型——结构化还是非结构化?分类变量还是数值变量 ...
2026-10-09指标体系是企业数字化分析、业务监控、经营决策的核心基础框架,是将零散数据转化为可衡量、可对比、可落地业务价值的关键体系。 ...
2026-10-08随着市场竞争日趋饱和,同质化低价竞争逐渐陷入内卷僵局,传统以价格、渠道、促销为核心的营销模式边际效益持续递减。在此背景下 ...
2026-10-08 很多数据分析师画过趋势图、做过业绩预测,但当被问到“这个月销售额增长20%,到底是长期趋势自然增长,还是促销活动的短期 ...
2026-10-08你有没有想过,手机里点外卖、刷社交软件、转一笔账,背后到底是谁在替你"记着账"? 答案其实很简单:数据库,以及跟它对话的那 ...
2026-10-07CDA数据分析师 出品 作者:李诗怡 一、数据分析四大思维 1. 对比思维:没有对比就没有分析 核心观点:单独一个数字没有意义,有 ...
2026-10-05Kimball 是方法,星型模型是它产出的形状。 很多人把"Kimball vs 星型模型"当成一道选择题——这本身就是个误会:Kimball 是动词 ...
2026-10-05写在开头 老板在微信上甩来一句: "帮我看下为什么销量跌了。" ” 你回工位,打开 SQL,开始写。查订单表、拉近三个月、按 ...
2026-10-03