SQL: Is there a possibility to convert numbers (1,2,3,4…) to letters (A,B,C,D…)

前端 未结 5 1662
伪装坚强ぢ
伪装坚强ぢ 2020-12-14 09:26

Is there a possibility to obtain letters (like A,B) instead of numbers (1,2) e.g. as a result of Dense_Rank function call(in MS Sql) ?

5条回答
  •  眼角桃花
    2020-12-14 09:54

    You can convert the values to an offset base-26 with a UDF:

    EDIT: Corrected function.

    create function dbo.HinkyBase26( @Value as BigInt ) returns VarChar(15) as
      begin
      -- Notes: 'A' = 0.  Negative numbers are not handled.
      declare @Result as VarChar(15) = '';
    
      if @Value = 0
        select @Result = 'A';
      else
        set @Value += 1;
      while @Value > 0
        select @Value -= 1, @Result = Char( ASCII( 'A' ) + @Value % 26 ) + @Result, @Value /= 26;
      return @Result;
      end;
    

    Sample values:

    select Arabic, dbo.HinkyBase26( Arabic ) as Alpha
      from ( values ( 0 ), ( 1 ), ( 25 ), ( 26 ), ( 51 ), ( 52 ),
        ( 27 * 26 - 1 ), ( 27 * 26 ),
        ( 33685567531 ) ) as Foo( Arabic );
    

    At ErikE's suggestion I ran a quick performance test on my notebook. 1,000,000 iterations of the UDF vs. the XML solution:

    declare @Count as Int;
    declare @Buffer as VarChar(16);
    declare @Start as DateTime;
    
    select @Count = 1000000, @Start = GetDate();
    while @Count > 0
      select @Buffer = dbo.HinkyBase26( @Count ), @Count -= 1;
    select DateDiff( ms, @Start, GetDate() ) as 'Elapsed Milliseconds'; -- 14,583    
    select @Count = 1000000, @Start = GetDate();
    while @Count > 0
      select @Buffer =
          (
             SELECT Char( ASCII( 'A' ) + (@Count - X.Low) / X.Div % 26)
             FROM
                (
                   SELECT 18279, 475254, 17576
                   UNION ALL SELECT 703, 18278, 676
                   UNION ALL SELECT 27, 702, 26
                   UNION ALL SELECT 1, 26, 1
                ) X (Low, High, Div)      
             WHERE @Count >= X.Low
             FOR XML PATH(''), TYPE
          ).value('.[1]', 'varchar(4)'), @Count -= 1;
    select DateDiff( ms, @Start, GetDate() ) as 'Elapsed Milliseconds'; -- 47,256
    

    The UDF was a little more than 3 times faster.

提交回复
热议问题