我用的是presto。我有一个数字ID字段。我想要一个列,将id中的数字相加。如果ID=1234,我想要一个输出10的列,即1+2+3+4。
我可以使用子字符串提取每个数字和求和,但有一个函数,我可以使用或更简单的方式?
您可以将@akuhn的答案中的regexp_extract_all
与Presto最近添加的lambda支持结合起来。这样就不需要unnest
了。如果不需要cast
和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)
如果我正确阅读你的问题,你想避免必须硬编码子字符串抓取ID中的每个数字,如substring (ID,1,1) + substring (ID,2,1) + ...substring (ID,n,1)
。这是不优雅的,只有在所有ID值长度相同的情况下才有效。
你可以做的是使用递归CTE。这种方法也适用于具有可变值长度的ID字段。
免责声明:这在技术上仍然使用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
首先使用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
;