【问题标题】:Add some specific value in each digit of number in SQL [closed]在 SQL 中的每个数字中添加一些特定值 [关闭]
【发布时间】:2018-10-30 18:19:14
【问题描述】:

我需要计算某个数字的公式

(1) 在特定数字的每个数字中添加 3

(2) 如果我们得到两位数相加后的结果,例如 10,11,12 等,那么只考虑最后一位数

例如,如果数字是 564843530,那么 enter code here 新号码将是 897176023。

【问题讨论】:

  • 你有什么尝试吗?如果是,请告诉我们
  • 不应该把564843530变成897176863吗? 5 + 3 = (1)0 怎么样?和3 + 3 = 2?

标签: sql-server tsql


【解决方案1】:

解决方案:

DECLARE @number int
SET @number = 564843530;

WITH DigitsTable AS 
(
    SELECT 0 AS Power10, ABS(@Number) AS Number
    UNION ALL
    SELECT Power10 + 1, Number / 10
    FROM DigitsTable
    WHERE Number > 10
)
SELECT SUM((((Number % 10) + 3) % 10) * POWER(10, Power10)) AS NewNumber
FROM DigitsTable
OPTION (MAXRECURSION 0);

输出:

897176863

说明:

此答案基于一个递归 CTE,它返回每个当前数字、新数字和乘数进行计算:

DECLARE @number int
SET @number = 564843530;

WITH DigitsTable AS 
(
    SELECT 0 AS Power10, ABS(@Number) AS Number
    UNION ALL
    SELECT Power10 + 1, Number / 10
    FROM DigitsTable
    WHERE Number > 10
)
SELECT 
    Power10,
    Number % 10 AS Digit,
    ((Number % 10) + 3) % 10 AS NewDigit,
    POWER(10, Power10) AS Multiplier
FROM DigitsTable
OPTION (MAXRECURSION 0);

递归 CTE 的输出:

Power10 Digit   NewDigit    Multiplier
0       0       3           1
1       3       6           10
2       5       8           100
3       3       6           1000
4       4       7           10000
5       8       1           100000
6       4       7           1000000
7       6       9           10000000
8       5       8           100000000

【讨论】:

    【解决方案2】:

    写这个:

    SELECT
    (
        SELECT RIGHT(SUBSTRING(DS.[number], v.[number] + 1, 1) + 3, 1)
        FROM 
        (
            SELECT '564843530' 
        ) DS ([number])
        INNER JOIN [master]..spt_values v on v.[number] < LEN(DS.[number])
        WHERE V.[type] = 'P'
        ORDER BY v.[number] 
        FOR XML PATH(''), TYPE
    ).value('.', 'VARCHAR(MAX)');
    

    算法很简单:

    1. 将字符串拆分为字符(在您的情况下为数字)
    2. 每个数字加 3
    3. 使用 RIGHT 仅获取第一个正确的字符
    4. 连接数字

    这应该适用于旧版本。如果您使用的是SQL Server 2016,则可以在SQL Server 2017 中使用STRING_SPLITSTRING_AGG 等函数。

    对于旧版本,您可以查找 SQL CLR 函数,以便编写自己的拆分和连接函数。例如,在我的系统中我可以这样做:

    如果对 SQL CLR 感兴趣,请查看以下link

    【讨论】:

    • Do not post images of code or errors! 图片和屏幕截图可以很好地添加到帖子中,但请确保帖子在没有它们的情况下仍然清晰有用。如果您发布代码或错误消息的图像,请确保您还复制并粘贴或直接在帖子中输入实际代码/消息。
    • @Rob 该解决方案以 T-SQL 代码的形式存在,可以复制。另一种说法仅适用于我的环境——截图显示概念和工作证明。请先阅读答案,并在您理解它们的情况下标记它们。
    • @gotqn 对预期结果的简单答案,我对这个答案印象深刻,兄弟我正在为这个问题编写脚本并执行了一些额外的步骤,但看到你的答案后我自己不想发帖。
    • @Sreenu131 谢谢。不用担心,提供另一种解决方案没有错(如果尚未发布)。
    【解决方案3】:

    假设 OP 提供的示例值是错误的(根据我的评论 564843530 不应该变成 8971768635 + 3 = (1)03 + 3 = 2 怎么样?”),那么这是我的方法,它利用了NGrams8k

    WITH VTE AS (
        SELECT 564843530 AS SomeNumber),
    Split AS(
        SELECT V.SomeNumber,
               NG.token,
               NG.position
        FROM VTE V
             CROSS APPLY dbo.NGrams8k(V.SomeNumber,1) NG)
    SELECT SomeNumber AS OldNumber,,
           CONVERT(bigint,(SELECT token + 3
                           FROM Split x
                           WHERE S.SomeNumber = x.SomeNumber
                           ORDER BY x.position
                           FOR XML PATH(''))) AS NewNumber
    FROM Split S
    GROUP BY S.SomeNumber;    
    

    【讨论】:

      【解决方案4】:

      试试这个

      DECLARE @n int, @inc int;
      SELECT @n = 564843530, @inc = 3;
      WITH t1(n, m, k, p)
      AS (
         SELECT @n AS n, CAST(0 AS int) AS m, CAST(0 AS int) AS k, CAST(0 AS bigint) AS p
         UNION ALL
         SELECT n / 10 AS n, n - round(n, -1, 1) AS m,  k + 1 AS k, CAST(power(10, k) AS bigint) AS p
         FROM t1 WHERE n > 0
      )
      SELECT SUM((CASE WHEN m > 10 - @inc THEN m - 10 + @inc ELSE m + @inc END) * p)
      FROM t1
      

      结果

      897176863
      

      【讨论】:

        猜你喜欢
        • 2023-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-12
        • 1970-01-01
        • 1970-01-01
        • 2013-05-30
        • 2019-07-05
        相关资源
        最近更新 更多