SQL 创建固定大小的数据桶,你想把数据放入若干个大小固定的桶(bucket)里,每个桶的元素个数是事先定好的。桶的个数可能是不确定的,但你希望确保每个桶有 5 个元素。例如,你希望基于 EMPNO
值为 EMP
表里的员工分组,一组最多 5 人,结果集显示如下。
SQL 创建固定大小的数据桶 问题描述
你想把数据放入若干个大小固定的桶(bucket)里,每个桶的元素个数是事先定好的。桶的个数可能是不确定的,但你希望确保每个桶有 5 个元素。例如,你希望基于 EMPNO
值为 EMP
表里的员工分组,一组最多 5 人,结果集显示如下。
SQL 创建固定大小的数据桶 解决方案
对于提供了排名函数的数据库而言,很容易解决本问题。在为每一行数据生成了一个序号之后,创建含有 5 个元素的桶的问题就变成了简单的除法问题。做过除法之后,我们只须针对商值向上取整即可。
DB2、Oracle 和 SQL Server
使用窗口函数 ROW_NUMBER OVER
,基于 EMPNO
为每个员工生成一个序号。然后用该序号除以 5 即可实现分组(SQL Server 需要调用 CEILING
函数,而不是 CEIL
函数)。
PostgreSQL 和 MySQL
使用标量子查询为每个 EMPNO
生成一个序号,然后用该序号除以 5 以创建分组。
SQL 创建固定大小的数据桶 扩展知识
DB2、Oracle 和 SQL Server
按照 EMPNO
排序后,窗口函数 ROW_NUMBER OVER
为每一行分配了一个排名或“行号”。
将 ROW_NUMBER OVER
函数的返回值除以 5 之后,下一步要调用函数 CEIL
(或 CEILING
)。理论上,除以 5,会把每 5 行数据划入一组。也就是说,会有 5 个值小于或等于 1,同时会有 5 个值大于 1 但小于或等于 2,剩下的一组则大于 2 但小于或等于 3(这一组由最后的 4 行数据构成,因为 EMP
表一共包含 14 行数据,并非 5 的整数倍)。
CEIL
函数将返回大于参数值的最小的整数。我们需要这样做,因为每一组的编号都是一个整数值。除法计算的结果以及 CEIL
函数的返回值显示如下。你可以按照从左到右、从 RN
到 DIVISION
再到 GRP
的顺序试着做一下运算。
PostgreSQL 和 MySQL
首先借助标量子查询基于 EMPNO
为每一行生成一个序号。
上述 RNK
值除以 5 之后,下一步要调用函数 CEIL
。理论上,除以 5 会把每 5 行数据划入一组。也就是说,会有 5 个值小于或等于 1,同时会有 5 个值大于 1 但小于或等于 2,剩下的一组则大于 2 但小于或等于 3(这一组由最后的 4 行数据构成,因为 EMP
表一共包含 14 行数据,并非 5 的整数倍)。除法计算的结果以及 CEIL
函数的返回值显示如下。你可以按照从左到右、从 RNK
到 DIVISION
再到 GRP
的顺序试着做一下运算。