Calling this from a before insert
trigger would result in separate sequences. But unless a for update lock is added somewhere duplicate values could result. (Haven't even compiled this yet alone tested it but it illustrates the pattern.)
public class AutoNumber {
private static Map<String, Integer> STARTING_VALUES = new Map<String, Integer>{
'abc' => 1,
'def' => 1000000,
'ghi' => 2000000,
...
};
public static void beforeInsert(List<MyObject__c> newValues) {
Set<String> values = new Set<String>();
for (MyObject__c o : newValues) {
if (o.Picklist__c != null) values.add(o.Picklist__c);
}
if (values.size() > 0) {
Map<String, Integer> maximums = queryMaximums(values);
for (MyObject__c o : newValues) {
Integer n = maximums.get(o.Picklist__c);
n++;
maximums.put(o.Picklist__c, n);
o.Number__c = n;
}
}
}
private static Map<String, Integer> queryMaximums(Set<String> values) {
Map<String, Integer> maximums = new Map<String, Integer>(STARTING_VALUES);
for (AggregateResult ar : [
select Picklist__c p, max(Number__c) m
from MyObject__c
where Picklist__c in :values
group by Picklist__c
]) {
maximums.put((String) ar.get('p'), ((Decimal) ar.get('m')).intValue());
}
return maximums;
}
}
PS
Given the for update problem, on second thoughts using a list custom setting to hold the last used value (where the name is the picklist value) probably makes more sense so the for update lock can be applied. Also avoids performance and governor limit problems in the aggregate query as the number of records grows.