首页 > 解决方案 > 对行进行分组,使每列的总和不超过 10

问题描述

我有一个看起来像的表:

col1
------
2
2
3
4
5
6
7

值按升序排序。

我想将每一行分配给标签为 0,1,...,n 的组,以便每个组的总数不超过 10。所以在上面的示例中,它看起来像这样:

col1 |label
------------
2   0
2   0
3   0
4   1
5   1
6   2
7   3

我尝试使用这个:

floor(sum(col1) OVER (partition by  ORDER BY col1 ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) /10))

但这不能正常工作,因为它正在执行以下操作:

floor(2/10) = 0
floor([2+2]/10) = 0
floor([2+2+3]/10) = 0
floor([2+2+3+4]/10) = 1
floor([2+2+3+4+5]/10 = 1
floor([2+2+3+4+5+6]/10 = 2
floor([2+2+3+4+5+6+7]/10) = 2

巧合的是,直到最后一次计算之前都是正确的,因为即使

[2+2+3+4+5+6+7] / 10 = 2.9

floor(2.9) = 2

它应该做的是实现 6+7 > 10,因此值为 7 的第 5 行需要在其自己的组中,因此迭代组号 + 1 并将该行分配到一个新组中。

我真正想要它做的是当它遇到一个和> 10然后设置组号=组号+ 1,将当前行分配到这个新组中,然后最后将新的开始行设置为当前行。

标签: sqlhadoophive

解决方案


评论太长了。

解决这个问题需要逐行扫描表。在 SQL 中,这将通过递归 CTE(或分层查询)。Hive 都不支持这些。

问题是每次定义一个组时,10 和总和之间的差值被“遗忘”。也就是说,当您在列表中更靠后时,较早发生的事情并不是对可用数据的简单累积。您需要知道它是如何分组的。

一个相关的问题可以解决的。相关问题会将所有行分配给大小为 10 的组,将行拆分为两组。然后,您将仅根据前一行的累积总和知道后一行所在的组。


推荐阅读