Sql 如何在oracle中基于值之和分配组
若我有两列,如下所示,我希望将记录放入桶中,使总和小于500。单个输入记录计数永远不会超过500。我想通过使用PL/SQL函数来实现Sql 如何在oracle中基于值之和分配组,sql,oracle,group-by,Sql,Oracle,Group By,若我有两列,如下所示,我希望将记录放入桶中,使总和小于500。单个输入记录计数永远不会超过500。我想通过使用PL/SQL函数来实现 id | bundle_count id | bundle_count| group_id -----|--------- -----|--------------|-------- 1 | 330 1
id | bundle_count id | bundle_count| group_id
-----|--------- -----|--------------|--------
1 | 330 1 | 330 | 1
2 | 150 2 | 150 | 1
3 | 200 =============> 3 | 200 | 2
4 | 280 Desired output 4 | 280 | 2
5 | 200 =============> 5 | 200 | 3
我可以用下面的查询来解决这个问题
SELECT id, bundle_count, ceil(sum(bundle_count) over(order by id) /500) as group_id
我可以用下面的查询来解决这个问题
SELECT id, bundle_count, ceil(sum(bundle_count) over(order by id) /500) as group_id
免责声明:这不是一个好答案,因为它在Oracle中不起作用 此解决方案在PostgreSQL中工作,不要求
ID
s是连续的。不幸的是,它在Oracle中不起作用,因为Oracle对递归CTE有一些限制;它不允许在递归CTE的迭代成员中限制
我想展示一下如何在PostgreSQL中干净利落地做到这一点。这是:
with recursive
x as (
select id, bundle_count, bundle_count as s, 1 as grp from t where id = 1
union all (
select t.id, t.bundle_count,
case when x.s + t.bundle_count < 500 then x.s + t.bundle_count
else t.bundle_count end,
case when x.s + t.bundle_count < 500 then x.grp else x.grp + 1 end
from t
join x on t.id > x.id
order by id
limit 1
)
)
select * from x order by id
请参见运行示例。免责声明:这不是一个好答案,因为它在Oracle中不起作用 此解决方案在PostgreSQL中工作,不要求
ID
s是连续的。不幸的是,它在Oracle中不起作用,因为Oracle对递归CTE有一些限制;它不允许在递归CTE的迭代成员中限制
我想展示一下如何在PostgreSQL中干净利落地做到这一点。这是:
with recursive
x as (
select id, bundle_count, bundle_count as s, 1 as grp from t where id = 1
union all (
select t.id, t.bundle_count,
case when x.s + t.bundle_count < 500 then x.s + t.bundle_count
else t.bundle_count end,
case when x.s + t.bundle_count < 500 then x.grp else x.grp + 1 end
from t
join x on t.id > x.id
order by id
limit 1
)
)
select * from x order by id
请参见运行示例。如果
ID
s是连续的,则可以在Oracle中执行此操作,如下所示:
with
x (id, bundle_count, s, grp) as (
select id, bundle_count, bundle_count, 1 from t where id = 1
union all (
select t.id, t.bundle_count,
case when x.s + t.bundle_count < 500 then x.s + t.bundle_count
else t.bundle_count end,
case when x.s + t.bundle_count < 500 then x.grp else x.grp + 1 end
from t
join x on t.id = x.id + 1
)
)
select * from x order by id;
请参阅上的运行示例
如果它们不是顺序的,则可以使用嵌套递归CTE。如果
ID
s是顺序的,则可以在Oracle中执行,如下所示:
with
x (id, bundle_count, s, grp) as (
select id, bundle_count, bundle_count, 1 from t where id = 1
union all (
select t.id, t.bundle_count,
case when x.s + t.bundle_count < 500 then x.s + t.bundle_count
else t.bundle_count end,
case when x.s + t.bundle_count < 500 then x.grp else x.grp + 1 end
from t
join x on t.id = x.id + 1
)
)
select * from x order by id;
请参阅上的运行示例
如果它们不是顺序的,则可以使用嵌套递归CTE。是否应该对ID进行排序?您使用的是什么版本的Oracle?@GordonLinoff-ID的顺序并不重要。只需要分配到不同的存储桶。我正在使用Oracle 18c。这使得这成为一个很难实现的装箱问题。如果有一行id为6且捆绑数量为15,该怎么办?既然该组中还有15人的空间,那么是否应该将其添加到
组id
=1中?或者应该将其添加到组\u id
=3中,因为我们正在按顺序处理行?@matthewmpeak-可以添加到任何存储桶中,如果总和低于500,则需要将其放入不同的存储桶中。应该订购id吗?您使用的是什么版本的Oracle?@GordonLinoff-ID的顺序并不重要。只需要分配到不同的存储桶。我正在使用Oracle 18c。这使得这成为一个很难实现的装箱问题。如果有一行id为6且捆绑数量为15,该怎么办?既然该组中还有15人的空间,那么是否应该将其添加到组id
=1中?或者应该将其添加到组\u id
=3,因为我们正在按顺序处理行?@matthewmpeak-可以添加到任何存储桶中,只要总和小于500,就需要将其放入不同的存储桶中。