复杂的SQL while循环

时间:2015-09-03 11:24:20

标签: sql sql-server

我正在尝试在SQL中创建一个while循环,它看起来有点复杂。这就是我需要它实现的目标:

  1. 遍历单个VARCHAR字符串(例如' 123')
  2. 如果第n个字符在字符串中处于偶数位置(例如字符串中的第2个,第4个....字母),则必须将其添加(SUM)到基础变量(让我们假设@ z)的
  3. 如果第n个字符在字符串中的奇数位置(例如字符串中的第1个,第3个....字母),则必须乘以2.如果这个新生成的值(让我们假设@y)小于10,必须将(SUM)添加到基础变量(仍然是相同的假设@z)。如果@y大于10,我们需要从@y中减去9,然后将它(SUM)添加到@z
  4. 在遍历整个字符串之后,这应返回由上述过程生成的数值。

    这是我到目前为止所做的,但我现在已经陷入困境(不用说,这段代码还没有用,但我想我正朝着正确的方向前进):

    : m_data(rhs.data)

    PS。输入将始终为100%数字值,但在我收到它时将其格式化为VARCHAR。

    更新

    样本字符串的预期结果是15

4 个答案:

答案 0 :(得分:3)

您可以在不使用循环的情况下执行此操作。这是使用Tally Table的解决方案:

DECLARE @x VARCHAR(20) = '12345'
DECLARE @z INT = 0 -- base value

;WITH E1(N) AS( -- 10 ^ 1 = 10 rows
    SELECT 1 FROM(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))t(N)
),
E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b), -- 10 ^ 2 = 100 rows
E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b), -- 10 ^ 4 = 10,000 rows
CteTally(N) AS(
    SELECT TOP(LEN(@x)) ROW_NUMBER() OVER(ORDER BY(SELECT NULL))
    FROM E4
),
CteChars(N, num) AS(
    SELECT
        t.N, CAST(SUBSTRING(@x, t.N, 1) AS INT)
    FROM CteTally t
    WHERE t.N <= LEN(@x)
)
SELECT
    SUM(
        CASE
            WHEN N % 2 = 0 THEN num
            WHEN num * 2 < 10 THEN num * 2
            ELSE (num * 2) - 9
        END
    ) + @z
FROM CteChars

CTE最多CteTally生成一个从1到LEN(@x)的数字列表。 CteChars逐个字符地将@x分成不同的行。然后,最终SELECT根据条件执行SUM

OUTPUT : 15

答案 1 :(得分:2)

检查下面是否有帮助

DECLARE @x varchar(20) = '12345'
DECLARE @p int = 1
DECLARE @result bigint=0;
DECLARE @tempval int =0;

WHILE @p <= len(@x)
BEGIN
SET @tempval = CONVERT(INT,substring(@x, @p, 1));    
if(@p%2 = 1)
BEGIN
    SET @tempval = @tempval * 2;
    IF(@tempval >= 10) SET @tempval = @tempval - 9;
END
SET @result = @result + @tempval;

  SET @p = @p + 1;
 END;

PRINT @result;--This is the result
 RETURN @x;

答案 2 :(得分:1)

    DECLARE @x INT = 12345
DECLARE @p int = len(@x)
DECLARE @z INT =0
PRINT @p%2
SET @x=@x/10
PRINT @x
WHILE @p > 0
BEGIN
  IF(@p%2 = 0)
  BEGIN
  SET @z=@z+@x%10
  SET @p=@p-1
 SET @x=@x/10
 END
 ELSE
 BEGIN 
 SET @z=@z+(2*(@x%10)) 
 SET @p=@p-1
 SET @x=@x/10
 IF(@x>=10)
 BEGIN
 SET @x=(@x/10+@x%10)
 END
 END
 END
 SELECT @z

答案 3 :(得分:1)

这里似乎没有必要使用while循环。 这可以通过CTE分割字符串和case语句来实现:

DECLARE @x varchar(20) = '12345';

with split(id, v) as (
    select 0, cast(0 as tinyint)
    union all
    select id+1, cast(SUBSTRING(@x, id+1, 1) as tinyint)
    From split
    Where id+1 <= len(@x)
)
Select Result = SUM(
    Case When id % 2 = 0 then v
        When v < 5 then v*2
        Else (v*2)-9
    End
    )
From split

输出= 15