Si j'ai deux colonnes comme ci-dessous, je voudrais mettre les enregistrements dans des seaux de telle sorte que la somme totale soit inférieure à 500. Le nombre d'enregistrements d'entrée individuels ne sera jamais supérieur à 500. Je voudrais réussir sans utiliser PL / SQL fonctions
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
3 Réponses :
Je suis capable de résoudre en utilisant la requête ci-dessous
SELECT id, bundle_count, ceil(sum(bundle_count) over(order by id) /500) as group_id
Clause de non-responsabilité: ce n'est pas une bonne réponse car elle ne fonctionne pas dans Oracle
Cette solution fonctionne dans PostgreSQL et ne nécessite pas que les ID
soient séquentiel. Malheureusement, cela ne fonctionne pas dans Oracle, car Oracle place quelques restrictions sur les CTE récursifs; il n'autorise pas LIMIT
dans le membre itératif du CTE récursif.
Je voulais montrer comment vous pouvez le faire proprement dans PostgreSQL. Le voici:
id bundle_count s grp -- ------------ --- --- 1 330 330 1 2 150 480 1 3 200 200 2 4 280 480 2 5 200 200 3
Résultat:
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
Voir l'exemple en cours d'exécution sur DB Fiddle .
Si les ID
sont séquentiels, vous pouvez le faire dans Oracle comme indiqué ci-dessous:
id bundle_count s grp -- ------------ --- --- 1 330 330 1 2 150 480 1 3 200 200 2 4 280 480 2 5 200 200 3
Résultat:
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;
Les identifiants doivent-ils être commandés? Quelle version d'Oracle utilisez-vous?
@GordonLinoff - L'ordre des identifiants n'est pas important. Juste besoin d'affecter dans différents seaux. J'utilise Oracle 18c
. . Cela en fait un problème de mise en boîte qui est assez difficile à mettre en œuvre.
Et s'il y avait une ligne avec
id
= 6 et unbundle_count
= 15? Cela devrait-il être ajouté àgroup_id
= 1, car il y a encore de la place pour 15 autres dans ce groupe? Ou devrait-il être ajouté àgroup_id
= 3, car nous traitons les lignes dans l'ordre?@MatthewMcPeak - peut être ajouté à n'importe quel compartiment, il est nécessaire de le placer dans différents compartiments, car la somme est inférieure à 500.
Très bonne question +1. J'ai ajouté une réponse qui fonctionne dans PostgreSQL. Je pense qu'il peut y avoir une autre option pour Oracle en utilisant des CTE récursifs imbriqués. Je vais essayer demain, car il est tard maintenant.