计算数字总和

Sip*_*ang 1 sql-server t-sql

我有一列包含数字:

Value
-----
123
452
021
111
...
Run Code Online (Sandbox Code Playgroud)

我想得到每个值的数字之和。

答案应该看起来像

Value  SumValue
-----  --------
123    6
452    11
021    3
111    3
...    ...  
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

我试过这个:

select value
     , case
           when len(value) = 2 then convert(int, left(value, 1))
                                  + convert(int, right(value, 1))
           when len(value) = 3 then convert(int, substring(convert(varchar(1), value), 1,1))
                                  + convert(int, substring(convert(varchar(1), value), 2,1))
                                  + convert(int, substring(convert(varchar(1), value), 3,1))
           else value
       end as SumNum
from get_number (000, 999);
Run Code Online (Sandbox Code Playgroud)

当我达到三位数时,它无法正确计算,在我看来必须有更好的解决方案。

EzL*_*zLo 5

这是一个无需将值转换为字符串的解决方案。

DECLARE @ValueTable TABLE (Value INT)

INSERT INTO @ValueTable (Value)
VALUES
    (5),
    (57),
    (3124),
    (645),
    (312114),
    (9000092)

SELECT
    OriginalValue = V.Value,
    SumOfDigits = 
        V.Value % POWER(10, 1) / POWER(10, 0)
        + V.Value % POWER(10, 2) / POWER(10, 1)
        + V.Value % POWER(10, 3) / POWER(10, 2)
        + V.Value % POWER(10, 4) / POWER(10, 3)
        + V.Value % POWER(10, 5) / POWER(10, 4)
        + V.Value % POWER(10, 6) / POWER(10, 5)
        + V.Value % POWER(10, 7) / POWER(10, 6)
        + V.Value % POWER(10, 8) / POWER(10, 7)
FROM
    @ValueTable AS V
Run Code Online (Sandbox Code Playgroud)

结果:

OriginalValue   SumOfDigits
5               5
57              12
3124            10
645             15
312114          12
9000092         20
Run Code Online (Sandbox Code Playgroud)

我将用一个例子来解释它是如何工作的,比如 value 645。为了得到最后一位数字,我们计算原始值的其余部分除以10(这是 mod 运算符%)。由于645 / 1064.5(如果在 SQL Server 上完成,它不会显示十进制值,因为它被视为INT),其余的是5.

SELECT 645 % 10 -- Result: 5
Run Code Online (Sandbox Code Playgroud)

为了获得倒数第二个数字,我们计算原始值的其余部分除以 100 ( 100 = 10 * 10 = 10 ^ 2 = POWER(10, 2))。由于除以 100 的其余部分可能会产生 2 位数字(从 0 到 99)而我们只需要十位数字,我们将此结果除以 10。除法的结果将是INT如果原始数字是INT,这正是我们想要什么。

SELECT 
    645 % 100,      -- Result: 45
    645 % 100 / 10  -- Result: 4 (second to last digit)
Run Code Online (Sandbox Code Playgroud)

为了让第 3 个最后一个,我们只需向 mod 运算符值和除法添加一个额外的 0(乘以 10):

SELECT 
    645 % 1000,         -- Result: 645
    645 % 1000 / 100    -- Result: 6 (third to last digit)
Run Code Online (Sandbox Code Playgroud)

这个也可以用POWER函数来写,也就是解中写的表达式。

SELECT 
    645 % POWER(10, 3),                 -- Result: 645
    645 % POWER(10, 3) / POWER(10, 2)   -- Result: 6 (third to last digit)
Run Code Online (Sandbox Code Playgroud)

在此解决方案中需要注意的一件事是,您必须添加尽可能多的添加(每个都有自己的%/),因为您可能在提供的值上有数字。

此外,如果您想在结果数字超过一位(例如 value 993 -> 21 -> 3)的情况下重复此过程,则有一个非常简单且有趣的算法,称为数字根


这是Andryi M提供的更具表现力的解决方案:

SELECT
    OriginalValue = V.Value,
    SumOfDigits = 
          V.Value            % 10
        + V.Value / 10       % 10
        + V.Value / 100      % 10
        + V.Value / 1000     % 10
        + V.Value / 10000    % 10
        + V.Value / 100000   % 10
        + V.Value / 1000000  % 10
        + V.Value / 10000000 % 10
FROM
    @ValueTable AS V
Run Code Online (Sandbox Code Playgroud)