SQL

2016-10-04 12 views
6

numaralı bir sayının toplamını basıyorum. Sayısal olan bir kimlik alanım var. Kimlikteki rakamları ekleyen bir sütun istiyorum. Yani ID = 1234 ise, 10 + 1 + 2 + 3 + 4 çıktısını veren bir sütun istiyorum.SQL

Her rakamı ayıklamak ve toplamak için substring kullanabilirim ama kullanabileceğim veya daha basit bir işlev var mı?

+0

belki kullanmak [ 'slice'] (https://prestodb.io/docs/current/functions/array.html) bir dizi oluşturmak ve daha sonra sadece dizi değerlerini toplamak için? – xQbert

cevap

0

Sorunuzu doğru bir şekilde okuyorsam, kimlikte substring (ID,1,1) + substring (ID,2,1) + ...substring (ID,n,1) gibi her numara için bir alt küme kapmak zorunda kalmamak gerekir. Hangi inelegant ve sadece tüm ID değerleri zaten aynı uzunlukta ise çalışır.

Bunun yerine, yinelemeli bir CTE kullanın. Bu şekilde, değişken değer uzunluklarına sahip ID alanları için de çalışır.

Yasal Uyarı: Bu teknik olarak hala substring kullanır, ancak dize bölmek hantal kod gömmek yakala

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 
0

İlk kullanım REGEXP_EXTRACT_ALL yapmaz. Ardından, çıkarılan rakamları sayılarına göre gruplandırmak ve bunların üzerine toplamak için CROSS JOIN UNNEST GROUP BY kullanın. İşte

,

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

Yakın zamanda Presto eklenen lambda desteğiyle @ akuhn cevabı dan regexp_extract_all birleştirebilirsiniz. Bu şekilde unnest'a ihtiyacınız yoktur. Kod gerçekten kendini açıklayıcı değilse ve varchar den cast ihtiyacı olacaktır:

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)