You can use the maximum value and a connect-by query to generate the upper and lower values for each range:
select ceil((level - 1) * int) as int_from,
floor(level * int) - 1 as int_to
from (select round(max(unit) / 3) as int from t42)
connect by level <= 3;
INT_FROM INT_TO
---------- ----------
0 76
77 153
154 230
And then do a left outer join to your original table to do the count for each range, so you get the zero value for the middle range:
with intervals as (
select ceil((level - 1) * int) as int_from,
floor(level * int) - 1 as int_to
from (select round(max(unit) / 3) as int from t42)
connect by level <= 3
)
select i.int_from || '-' || i.int_to as range,
count(t.unit)
from intervals i
left join t42 t
on t.unit between i.int_from and i.int_to
group by i.int_from, i.int_to
order by i.int_from;
RANGE COUNT(T.UNIT)
---------- -------------
0-76 4
77-153 0
154-230 2