SQL Суммирование цифр числа

#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
;