我有一个包含3列的表格,如下所示:
id | num_rows id | num_rows | group_id
-----|--------- -----|----------|--------
2502 | 330 2502 | 330 | 9
3972 | 150 3972 | 150 | 9
3988 | 200 =============> 3988 | 200 | 8
4228 | 280 Desired output 4228 | 280 | 8
3971 | 510 =============> 3971 | 510 | 1
52 | 1990 52 | 1990 | 2
895 | 2000 895 | 2000 | 3
812 | 5596 812 | 5596 | 4
1600 | 7462 1600 | 7462 | 5
910 | 7526 910 | 7526 | 6
638 | 11569 638 | 11569 | 7
id
是某事物的唯一标识符,而num_rows
对应于每个id
在另一个表中的行数。
我想对行(即id
列)进行分组,以使num_rows
的总和永远不超过指定值(在这种情况下,假设500
)。 / p>
简而言之:我想将id
分组到存储桶中,没有存储桶的行多于500
。如果id
大于限制,那么它将获得自己的单独的组/存储桶。
到目前为止,我已经能够使用以下查询来分离出较大的id
,但是我无法为id
的其余子集创建组。
SELECT id,
num_rows,
SUM(CASE WHEN num_rows > 500 THEN 1 ELSE 0 END) OVER(ORDER BY num_rows) AS group_id
FROM myTable;
id | num_rows | group_id
-----|----------|--------
2502 | 330 | 0
3972 | 150 | 0
3988 | 200 | 0
4228 | 280 | 0
3971 | 510 | 1
52 | 1990 | 2
895 | 2000 | 3
812 | 5596 | 4
1600 | 7462 | 5
910 | 7526 | 6
638 | 11569 | 7
谢谢。
答案 0 :(得分:1)
我个人更喜欢使用pl / sql函数来完成此任务,但是如果您想在纯sql中执行此操作,则可以使用以下查询:
WITH ord AS (SELECT id, num_rows, ROWNUM ord FROM myTable)
, rek(ord, id, num_rows, sum_rows, groupId) AS
(SELECT ord, id, num_rows, num_rows, 1 FROM ord WHERE ord = 1
UNION ALL
SELECT rek.ord +1
, ord.id
, ord.num_rows
, CASE WHEN rek.sum_rows + ord.num_rows > 500
THEN ord.num_rows
ELSE rek.num_rows + ord.num_rows
END
, CASE WHEN rek.sum_rows + ord.num_rows > 500
THEN rek.groupID + 1
ELSE rek.groupID
END
FROM rek
JOIN ORD
ON ord.ord = rek.ord+1)
SELECT id, num_rows, groupid
FROM rek
/
请注意,此查询不会搜索要建立组的匹配条目,以使总和<500,因为这与所谓的背包问题(s。https://en.wikipedia.org/wiki/Knapsack_problem)密切相关,这几乎很容易解决...
答案 1 :(得分:-1)
如果您不希望按顺序进行操作,则可以按如下所示不使用任何行来进行分组
SELECT id,
num_rows,
ceil(num_rows/500) AS group_id
FROM myTable;
这应该是每500行块的新ID。