来自0-Z的SQL分子

时间:2016-01-19 13:28:34

标签: sql sql-server tsql

是否有一种简单优雅的方法可以在SQL中创建分子,执行以下操作:

  • 三位数
  • 每个数字可以有一个0-Z的数字:Min 000,Max ZZZ
  • 例如,让我们采取:129,增加1后,新号码将是12A
  • 当数字为15Z时,增加1后会变为160,依此类推。

我只能使用SQL,没有代码! 我只需要一个枚举器,而不是像其他人建议的那样在基数之间进行转换。

有人可以帮我写一个UDF。

我得到了一个优秀而优雅的答案,我在下面标出。

谁曾将我的问题标记为否定,请重新考虑,因为这是一个真正的问题,而不是一个古怪的问题,它为我节省了很多变通方法。

提前致谢。

5 个答案:

答案 0 :(得分:2)

生成笛卡儿并取第一个大于输入值的值:

declare @v varchar(10) = '129'

;with cte as(select * from (values('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9')
                                 ,('A'),('B'),('C'),('D'),('E'),('F'),('G'),('H'),('I'),('J'),('K')
                                 ,('L'),('M'),('N'),('O'),('P'),('Q'),('R'),('S'),('T'),('U'),('V')
                                 ,('W'),('X'),('Y'),('Z')) t(n))
select top 1 c1.n + c2.n + c3.n as n
from cte c1
cross join cte c2
cross join cte c3
where c1.n + c2.n + c3.n > @v
order by n

答案 1 :(得分:1)

您应该将值存储为数字,然后在需要时将其转换为格式。

这是一个添加奇怪格式的脚本。该脚本不检查原始值中的溢出或无效数据:

DECLARE @original char(3) = '129'

DECLARE @val int = 
  CASE WHEN RIGHT(@original, 1) > '9' THEN ASCII(RIGHT(@original, 1)) - 55
    ELSE RIGHT(@original, 1) END
  +CASE WHEN SUBSTRING(@original, 2,1) > '9' 
    THEN ASCII(SUBSTRING(@original, 2,1)) - 55 ELSE SUBSTRING(@original, 2,1) END * 36
  +CASE WHEN LEFT(@original, 1) > '9' 
    THEN ASCII(LEFT(@original, 1)) - 55 ELSE LEFT(@original, 1) END * 36 * 36
  +1 -- increase 1

SELECT 
  CHAR(CASE WHEN @val / 36 / 36 > 9 THEN @val / 36 / 36 + 55 
            ELSE @val / 36 / 36+48 END)+
  CHAR(CASE WHEN (@val / 36) % 36 > 9 THEN (@val / 36) % 36 + 55 
            ELSE (@val / 36) % 36+48 END)+
  CHAR(CASE WHEN @val % 36 % 36 > 9 THEN @val % 36 % 36 + 55
            ELSE @val % 36 % 36+48 END)

结果:

12A

答案 2 :(得分:1)

我建议您使用此查询在数据库中创建此表

 ;WITH Ch AS
 (  select i,C=CASE WHEN i<=10 THEN Char(47+i) ELSE CHAR(54+i) END FROM (SELECT TOP 36 row_number() over(order by object_id) i  from sys.objects) t  )

SELECT row_number() over(order by Ch.c,Ch2.c,Ch3.c) i,
Ch.c + Ch2.c + Ch3.c C INTO B36 FROM Ch CROSS JOIN Ch Ch2 CROSS JOIN Ch Ch3

所以你可以在i&amp; C列 然后,您可以从此表中查询索引寻求最快速度的转换,并按如下方式进行优化:

SELECT C FROM B36 WHERE i=3728

使用

进行反向编码
SELECT i FROM B36 WHERE C='AG7'

答案 3 :(得分:0)

我可以给你一个这样的转换器:

char(48 + (i / (36 * 36)) + CASE WHEN (i / (36 * 36)) > 9 THEN 7 ELSE 0 END) + 
char(48 + (i / 36) % 36 + CASE WHEN (i / 36) % 36 > 9 THEN 7 ELSE 0 END) + 
char(48 + i % 36 + CASE WHEN i % 36 > 9 THEN 7 ELSE 0 END)

可以将int值转换为您想要的值。

<强> [SQL Fiddle Demo]

修改

我也可以这样给你转换上面的转换器:
(例如:@t varchar(max) = '12Z'

(ASCII(LEFT(@t, 1)) - 48 - CASE WHEN ASCII(LEFT(@t, 1)) > ASCII('9') THEN 7 ELSE 0 END) * 36 * 36 +
(ASCII(SUBSTRING(@t,2,1)) - 48 - CASE WHEN ASCII(SUBSTRING(@t,2,1)) > ASCII('9') THEN 7 ELSE 0 END) * 36 +
(ASCII(RIGHT(@t, 1)) - 48 - CASE WHEN ASCII(RIGHT(@t, 1)) > ASCII('9') THEN 7 ELSE 0 END)

答案 4 :(得分:0)

将bigint转换为Base36的函数

CREATE FUNCTION dbo.fnBase36
(
    @Val BIGINT
)
RETURNS VARCHAR(13)
AS
BEGIN
    DECLARE @Result VARCHAR(13) = ''

    IF (@Val <= 0)
    BEGIN
        RETURN '0'
    END

    WHILE (@Val > 0)
    BEGIN
        SELECT @Result = CHAR(@Val % 36 + CASE WHEN @Val % 36 < 10 THEN 48 ELSE 55 END) + @Result,
               @Val = FLOOR(@Val/36)
    END

    RETURN @Result
END
GO
  

选择dbo.fnBase36(321)
   - 回复8X