#sql #presto
#sql #presto
Вопрос:
я использую presto. У меня есть поле идентификатора, которое является числовым. Мне нужен столбец, который суммирует цифры в идентификаторе. Итак, если ID = 1234, мне нужен столбец, который выводит 10, т.е. 1 2 3 4 .
Я мог бы использовать substring для извлечения каждой цифры и ее суммирования, но есть ли функция, которую я могу использовать, или более простой способ?
Комментарии:
1. может быть, использовать
slice
для генерации массива, а затем просто суммировать значения в массиве?
Ответ №1:
Вы можете объединить regexp_extract_all
ответ @akuhn с поддержкой lambda, недавно добавленной в Presto. Таким образом, вам не нужно unnest
. Код был бы действительно понятен, если бы не необходимость в cast
to и from varchar
:
presto> select
reduce(
regexp_extract_all(cast(x as varchar), 'd'), -- split into digits array
0, -- initial reduction element
(s, x) -> s cast(x as integer), -- reduction function
s -> s -- finalization
) sum_of_digits
from (values 1234) t(x);
sum_of_digits
---------------
10
(1 row)
Ответ №2:
Если я правильно читаю ваш вопрос, вы хотите избежать необходимости жестко кодировать захват подстроки для каждой цифры в идентификаторе, например substring (ID,1,1) substring (ID,2,1) ...substring (ID,n,1)
. Это неэлегантно и работает только в том случае, если все ваши значения ID имеют одинаковую длину.
Вместо этого вы можете использовать рекурсивный CTE. Выполнение этого способа также работает для полей идентификаторов с длиной переменных значений.
Отказ от ответственности: технически это все еще используется substring
, но не выполняет неуклюжий захват жесткого кода
WITH recur (ID, place, ID_sum)
AS
(
SELECT ID, 1 , CAST(substring(CAST(ID as varchar),1,1) as int)
FROM SO_rbase
UNION ALL
SELECT ID, place 1, ID_sum substring(CAST(ID as varchar),place 1,1)
FROM recur
WHERE len(ID) >= place 1
)
SELECT ID, max(ID_SUM) as ID_sum
FROM recur
GROUP BY ID
Ответ №3:
Сначала используйте REGEXP_EXTRACT_ALL
для разделения строки. Затем используйте CROSS JOIN UNNEST GROUP BY
для группировки извлеченных цифр по их количеству и суммирования по ним.
Здесь,
WITH my_table AS (SELECT * FROM (VALUES ('12345'), ('42'), ('789')) AS a (num))
SELECT
num,
SUM(CAST(digit AS BIGINT))
FROM
my_table
CROSS JOIN
UNNEST(REGEXP_EXTRACT_ALL(num,'d')) AS b (digit)
GROUP BY
num
;