Самый быстрый способ - создать справочную таблицу, которая сопоставляет ранги с именами групп.Вы можете сделать это, используя JavaScript UDF с сохранением состояния (инициализация карты только один раз).
Но вы также можете просто сделать это в SQL
Определение таблицы
Простое отображение изчисло в строку
create or replace table rank2group(rank integer, grp string);
UDF для генерации имени группы
Ваш код действительно очень длинный.
Вместо этого мы можем создать функцию, которая для данного ранга group_size
и group_base
(число, из которого формируются группы group_size
) генерирует строку.
Примечаниеэта функция будет работать медленнее, чем ваш код, поскольку она генерирует строку из входных данных, но мы будем использовать ее только для заполнения таблицы поиска, поэтому это не имеет значения.
create or replace function group_name(rank integer, group_base integer, group_size integer)
returns varchar
as $$
(group_base + 1 + group_size * floor((rank - 1 - group_base) / group_size))
|| '-' ||
(group_base + group_size + group_size * floor((rank - 1 - group_base) / group_size))
$$;
Пример выходных данных:
select group_name(101, 100, 100), group_name(1678, 500, 500), group_name(15000, 10000, 5000);
---------------------------+----------------------------+--------------------------------+
GROUP_NAME(101, 100, 100) | GROUP_NAME(1678, 500, 500) | GROUP_NAME(15000, 10000, 5000) |
---------------------------+----------------------------+--------------------------------+
101-200 | 1501-2000 | 10001-15000 |
---------------------------+----------------------------+--------------------------------+
Генерация данных таблицы
Мы сгенерируем значения, отображающие только диапазон 1 .. 60000
, используя генераторы Snowflake, group_name
и ваш упрощенный оператор CASE
:
создать или заменить таблицу rank2group (rank integer, строка grp);
insert into rank2group
select rank,
CASE
WHEN rank <=100 THEN to_varchar(rank)
-- groups of size 100, starting at 100
WHEN rank <=500 then group_name(rank, 100, 100)
WHEN rank <=10000 then group_name(rank, 500, 500)
-- groups of size 5000, starting at 10000
WHEN rank <=15000 then group_name(rank, 10000, 5000)
WHEN rank <=60000 then group_name(rank, 15000, 15000)
ELSE 'Bottom'
END AS "TRANSACTION GROUPS"
from (
select row_number() over (order by 1) as rank
from table(generator(rowCount=>60000))
);
Использование
Чтобы использовать ее, мы просто присоединяемся к rank
.Обратите внимание, вам нужно outer join
, а затем ifnull
для значений Bottom
.Например, используя сгенерированный input
, который создает экспоненциально увеличивающиеся числа:
with input as (
select 1 + (seq8() * seq8() * seq8()) AS rank
from table(generator(rowCount=>50))
)
select input.rank, ifnull(grp, 'Bottom') grp
from input left outer join rank2group on input.rank = rank2group.rank
order by input.rank;
--------+-------------+
RANK | GRP |
--------+-------------+
1 | 1 |
2 | 2 |
9 | 9 |
28 | 28 |
65 | 65 |
126 | 101-200 |
217 | 201-300 |
344 | 301-400 |
513 | 501-1000 |
730 | 501-1000 |
1001 | 1001-1500 |
1332 | 1001-1500 |
1729 | 1501-2000 |
2198 | 2001-2500 |
2745 | 2501-3000 |
3376 | 3001-3500 |
4097 | 4001-4500 |
4914 | 4501-5000 |
5833 | 5501-6000 |
6860 | 6501-7000 |
8001 | 8001-8500 |
9262 | 9001-9500 |
10649 | 10001-15000 |
12168 | 10001-15000 |
13825 | 10001-15000 |
15626 | 15001-30000 |
17577 | 15001-30000 |
19684 | 15001-30000 |
21953 | 15001-30000 |
24390 | 15001-30000 |
27001 | 15001-30000 |
29792 | 15001-30000 |
32769 | 30001-45000 |
35938 | 30001-45000 |
39305 | 30001-45000 |
42876 | 30001-45000 |
46657 | 45001-60000 |
50654 | 45001-60000 |
54873 | 45001-60000 |
59320 | 45001-60000 |
64001 | Bottom |
68922 | Bottom |
74089 | Bottom |
79508 | Bottom |
85185 | Bottom |
91126 | Bottom |
97337 | Bottom |
103824 | Bottom |
110593 | Bottom |
117650 | Bottom |
--------+-------------+
Возможная оптимизация
Если ваши диапазоны всегда кратны или равны 100, вы можете сделать таблицу в 100 раз меньше,сохраняются только значения, оканчивающиеся на 00
, а затем объединяются, например, CEIL(rank)+1
.
Но тогда вам также нужно обрабатывать значения 1..100
после объединения, например, IFNULL(grp, IFF(rank <= 100, rank::varchar, 'Bottom'))