逻辑以将数字拆分并添加到分配的权重中n SQL

时间:2018-08-12 23:42:55

标签: sql-server

我有以下要求。 下面是程序。 我没有得到预期的结果。 请更正我要去哪里的地方。

0   0   0   0   0   0   1   1   1   5   0   8   0   0   2   0   0   4   0   0   4   0   0   1   0   0   0   0   4   0   0   0   0   0   0   0   0   0   4   3   1   2   4   0   1   1   0   1   1   0   0   0   0   0   0   1   1   1   0                                                                               

从左到右分配权重7、5、3、2:

7   5   3   2   7   5   3   2   7   5   3   2   7   5   3   2   7   5   3   2   6   5   3   2   7   5   3   2   5   5   3   2   7   5   3   2   7   5   3   2   7   5   3   2   7   5   3   2   7   5   3   2   7   5   3   2   7   5   3                                                                               

每个数字乘以分配的权重:

0   0   0   0   0   0   3   3   7   25  0   16  0   0   6   0   0   20  0   0   24  0   0   2   0   0   0   0   20  0   0   0   0   0   0   0   0   0   12  6   7   10  12  0   7   5   0   2   7   0   0   0   0   0   0   2   7   5   0                                                                               

分割并添加数字:

0   0   0   0   0   0   3   3   7   7   0   7   0   0   6   0   0   2   0   0   6   0   0   2   0   0   0   0   2   0   0   0   0   0   0   0   0   0   3   6   7   1   3   0   7   7   7   2   7   0   0   0   0   0   0   2   2   5   0   

总数是104

将和除以模数10:

104/10 = 10.4

减去模10的余数:

10-4 = 6

校验位:

6

2 个答案:

答案 0 :(得分:1)

由于您可以使用基于集合的解决方案来完成查询,因此我没有进行查询。 不需要光标。只需使用递归生成数字表即可。如果您有数字表,请使用它

declare @str varchar(100) = '00000011150800200400400100004000000000431240110110000001110'

; with 
number as   -- replace with a number or tally table if you have one
(
    select  n = 1
    union all
    select  n = n + 1
    from    number
    where   n   < len(@str)
),
weights as
(
    select  n = 1, weights = 7  union all
    select  n = 2, weights = 5  union all
    select  n = 3, weights = 3  union all
    select  n = 0, weights = 2
)
select  check_digit = 10 
                    - ( sum(s.d1 + s.d2) % 10 )
from    number n
        inner join weights w    on  n.n % 4 = w.n
        cross apply
        (
            select  d1 = convert(int, substring(@str, n.n, 1)) * w.weights / 10,
                    d2 = convert(int, substring(@str, n.n, 1)) * w.weights % 10
        ) s

您可以使用以下select子句来验证间歇性结果

select  n.n, 
        digit = convert(int, substring(@str, n.n, 1)), 
        [weight] = w.weights,
        [digit x weight] = convert(int, substring(@str, n.n, 1)) * w.weights,
        s.d1, s.d2

答案 1 :(得分:0)

This worked for me. If there is any better solution please share.
I am calling another function that adds no splits in to the main function.

开始    宣告@iCursor INT,            @aCursor Varchar,            @cCursor_Value INT,            @iValidation_Value INT,            @isum INT            -@ jcursor INT

-- for 7
   SELECT @iCursor = 1
   SELECT @iValidation_Value = 0
   SELECT @isum = 0
   --SELECT @jcursor = 1

   WHILE @iCursor <= @p_iStr_Len
      BEGIN
         SELECT @cCursor_Value = CONVERT(INT, SUBSTRING(REPLACE(REPLACE(@p_cValidation_Str,'M','4'),'m','4'), @iCursor, 1))
         --SELECT @cCursor_Value = CONVERT(INT, SUBSTRING(REPLACE(@p_cValidation_Str,'M','4'), @iCursor, 1))
         SELECT @iValidation_Value = (@cCursor_Value * 7)
         SELECT @iCursor = @iCursor + 4

       --WHILE @jcursor <= datalength(@iValidation_Value)
              select @isum= @isum + [frdmrpt].[FN_Sumofdigits](@iValidation_Value)
       --     BEGIN SELECT @isum = @isum + CONVERT(INT,SUBSTRING(CONVERT(VARCHAR,@iValidation_Value),@jcursor,1))
       --     SET @jcursor = @jcursor+1
       --END

      END

--for 5

   SELECT @iCursor = 2
   SELECT @iValidation_Value = 0
   --SELECT @jcursor = 1

   WHILE @iCursor <= @p_iStr_Len
      BEGIN
         SELECT @cCursor_Value = CONVERT(INT, SUBSTRING(@p_cValidation_Str, @iCursor, 1))
         SELECT @iValidation_Value = (@cCursor_Value * 5)
         SELECT @iCursor = @iCursor + 4
         SELECT @isum= @isum + [frdmrpt].[FN_Sumofdigits](@iValidation_Value)

      END


--for 3
   SELECT @iCursor = 3
   SELECT @iValidation_Value = 0

   WHILE @iCursor <= @p_iStr_Len
      BEGIN
         SELECT @cCursor_Value = CONVERT(INT, SUBSTRING(@p_cValidation_Str, @iCursor, 1))
         SELECT @iValidation_Value = (@cCursor_Value * 3)
         SELECT @iCursor = @iCursor + 4
         SELECT @isum= @isum + [frdmrpt].[FN_Sumofdigits](@iValidation_Value)

      END



--for 2   
   SELECT @iCursor = 4
   SELECT @iValidation_Value = 0

   WHILE @iCursor <= @p_iStr_Len
      BEGIN
         SELECT @cCursor_Value = CONVERT(INT, SUBSTRING(@p_cValidation_Str, @iCursor, 1))
         SELECT @iValidation_Value = (@cCursor_Value * 2)
         SELECT @iCursor = @iCursor + 4
         SELECT @isum= @isum + [frdmrpt].[FN_Sumofdigits](@iValidation_Value)

      END



--RETURN ( @isum)


      IF @isum % 10 = 0
         SELECT @isum = 0
      ELSE
         SELECT @isum = 10 - (@isum % 10)

      RETURN (Replace(@p_cValidation_Str,'M',4) + Convert(char(1), @isum))
   END