如果你的桶总是从 1 开始并且增量=1,你可以使用非常简单的mod(row_number, max(bucket)):
select
line, term, course
,1+mod(-1+row_number()over(partition by line order by course),max(bucket)) bucket_n
from t
group by line, term, course
order by line,course;
带有样本数据的完整示例:
with t(LINE ,BUCKET ,TERM ,COURSE) as (
select 1001, 1, 'FA18', 'COURSE 101' from dual union all
select 1001, 1, 'SP19', 'COURSE 102' from dual union all
select 1001, 1, 'SP19', 'COURSE 103' from dual union all
select 1001, 1, 'FA19', 'COURSE 104' from dual union all
select 1001, 2, 'FA18', 'COURSE 101' from dual union all
select 1001, 2, 'SP19', 'COURSE 102' from dual union all
select 1001, 2, 'SP19', 'COURSE 103' from dual union all
select 1001, 2, 'FA19', 'COURSE 104' from dual union all
select 2001, 1, 'FA18', 'COURSE 201' from dual union all
select 2001, 1, 'SP19', 'COURSE 202' from dual union all
select 2001, 1, 'FA20', 'COURSE 203' from dual union all
select 2001, 2, 'FA18', 'COURSE 201' from dual union all
select 2001, 2, 'SP19', 'COURSE 202' from dual union all
select 2001, 2, 'FA20', 'COURSE 203' from dual union all
select 2001, 3, 'FA18', 'COURSE 201' from dual union all
select 2001, 3, 'SP19', 'COURSE 202' from dual union all
select 2001, 3, 'FA20', 'COURSE 203' from dual
)
select
line, term, course
,1+mod(-1+row_number()over(partition by line order by course),max(bucket)) bucket_n
from t
group by line, term, course
order by line,course;
结果:
LINE TERM COURSE BUCKET_N
------- ------- ----------- --------
1001 FA18 COURSE 101 1
1001 SP19 COURSE 102 2
1001 SP19 COURSE 103 1
1001 FA19 COURSE 104 2
2001 FA18 COURSE 201 1
2001 SP19 COURSE 202 2
2001 FA20 COURSE 203 3
另一个有趣的变体是聚合桶并按位置提取值mod(rownumber, count(buckets)) - 与之前的解决方案相反,它适用于任何桶:
select
line, term, course
,xmlcast(
xmlelement(
"buckets",
xmlagg(xmlelement("bucket", bucket))
).extract('/buckets/*['||
(1+mod(-1+row_number()over(partition by line order by course),count(bucket)))
||']')
as int) bucket_n_2
from t
group by line, term, course
order by line,course;
完整的测试用例:
with t(LINE ,BUCKET ,TERM ,COURSE) as (
select 1001, 1, 'FA18', 'COURSE 101' from dual union all
select 1001, 1, 'SP19', 'COURSE 102' from dual union all
select 1001, 1, 'SP19', 'COURSE 103' from dual union all
select 1001, 1, 'FA19', 'COURSE 104' from dual union all
select 1001, 2, 'FA18', 'COURSE 101' from dual union all
select 1001, 2, 'SP19', 'COURSE 102' from dual union all
select 1001, 2, 'SP19', 'COURSE 103' from dual union all
select 1001, 2, 'FA19', 'COURSE 104' from dual union all
select 2001, 1, 'FA18', 'COURSE 201' from dual union all
select 2001, 1, 'SP19', 'COURSE 202' from dual union all
select 2001, 1, 'FA20', 'COURSE 203' from dual union all
select 2001, 2, 'FA18', 'COURSE 201' from dual union all
select 2001, 2, 'SP19', 'COURSE 202' from dual union all
select 2001, 2, 'FA20', 'COURSE 203' from dual union all
select 2001, 3, 'FA18', 'COURSE 201' from dual union all
select 2001, 3, 'SP19', 'COURSE 202' from dual union all
select 2001, 3, 'FA20', 'COURSE 203' from dual
)
select
line, term, course
,1+mod(-1+row_number()over(partition by line order by course),max(bucket)) bucket_n
,xmlcast(
xmlelement(
"buckets",
xmlagg(xmlelement("bucket", bucket))
).extract('/buckets/*['||
(1+mod(-1+row_number()over(partition by line order by course),count(bucket)))
||']')
as int) bucket_n_2
from t
group by line, term, course
order by line,course;
-
xmlagg(xmlelement("bucket", bucket)) 聚合所有桶数。
-
extract('/buckets/*[N]) - 从聚合值中提取 N 的桶
-
(1+mod(-1+row_number()over(partition by line order by course),count(bucket))) - 计算第 N 个桶
结果:BUCKET_N - 以前的,BUCKET_N_2 - 新变种:
LINE TERM COURSE BUCKET_N BUCKET_N_2
1001 FA18 COURSE 101 1 1
1001 SP19 COURSE 102 2 2
1001 SP19 COURSE 103 1 1
1001 FA19 COURSE 104 2 2
2001 FA18 COURSE 201 1 1
2001 SP19 COURSE 202 2 3
2001 FA20 COURSE 203 3 2