T-SQL:10,000個の重複しない番号を26文字で表す

26047 ワード

庭の友達がnewid()で書いているのを見て、
insert into T 
select top 10000 
        replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(lower(left(replace(newid(), 
                                                              '-', ''), 20)), 
                                                              '0', 'a'), 1, 
                                                              'b'), 2, 'c'), 3, 
                                                              'd'), 4, 'e'), 5, 
                                                'f'), 6, 'g'), 7, 'h'), 8, 'i'), 
                9, 'j') as col 
from    sys.all_columns , 
        sys.all_objects 

ここでnewid()は、「F 6 BCE 480-834 B-4 FB 9-B 905-B 568 B 9 F 9 C 7 A 3」(32文字と数字に4本の横線を加える)のようなGUIDを生成する、理論的には重複しない.問題は、その中の数字をアルファベットに変換すると、生成されたアルファベットシーケンスの1文字がGUIDの1文字に対応するも、1文字に対応するもよい.言い換えれば、このアルファベットシーケンスをGUIDに「翻訳」する場合、最大2の32回の異なるGUIDに対応することができる(計算機で計算する:4294967296個).このように繰り返しが現れる確率は大きくないが、少なくとも理論的には繰り返しが起こらないとは保証できない.
 
実は、0から10000まで、この数字自体は繰り返さないので、いっそアルファベットに変換すればいいのです.これは方法1です.
declare @n int
set @n = 0;
while @n<10000
begin
    print replace(replace(convert(varchar(5), @n), '0', 'a'), '1', 'b') ---replace('2', 'c')....
    set @n = @n+1
end

 
上に見えるのはa,b,c...h,i,jの10文字の組み合わせは、26文字で使えますか?もちろんいいです.十進法を「二十六進数」に変換してみてください:a=0,b=1....z = 25. では、ba=26.はい、大丈夫です.そうしてもいいです.
declare @one int, @n int, @res varchar(5)
set @n = 20 -- test
if (@n = 0) set @res = 'a';
else set @res = ''
while @n > 0
begin
    set @one = @n%26
    set @res = CHAR(@one+97) + @res
    set @n = @n/26
end
print @res

上は「26進法」の問題を解決した.whileサイクルはネスト可能であることも知る、10000個の番号を「26進法」で表すことができる.方法2:
declare @n int
set @n = 0
while @n < 10000
begin
    declare @one int, @num int, @res varchar(5)
    set @num = @n
    if (@num = 0) set @res = 'a'
    else set @res = ''
    while @num>0
    begin
        set @one=@num%26
        set @res = CHAR(@one+97) + @res
        set @num = @num/26
    end
    
    print @res    
    set @n = @n+1
end

 
また、SQL SERVER 2008は、テーブル値関数の提供を開始します.
select ch from
    (
      values
        ('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')
    ) as char_table(ch)

26文字で交差接続することを考えてみてください.26*26*26=17576、3枚の表で十分です.方法3:
with chars as 
( select ch from
    (
      values
        ('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')
    ) as char_table(ch)
) 

select a.ch, b.ch, c.ch, (a.ch+b.ch+c.ch) as rn
from chars as a
cross join chars as b
cross join chars as c

-- results
ch   ch   ch   rn
---- ---- ---- ----
a    a    a    aaa
a    b    a    aba
a    c    a    aca
a    d    a    ada
....

2番目の列から増加し、3番目の列から開始します.
with chars as 
( select ch from
    (
      values
        ('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')
    ) as char_table(ch)
),
bc as (select c1.ch as chb, c2.ch as chc from chars as c1 cross join chars as c2),
abc as (select ch as cha, chb, chc from chars cross join bc) 

select top 10000 cha, chb, chc, (cha+chb+chc) as rn from abc

-- results
cha  chb  chc  rn
---- ---- ---- ----
a    a    a    aaa
a    a    b    aab
a    a    c    aac
a    a    d    aad
....

さあ、ご飯を食べに行きます!
転載先:https://www.cnblogs.com/Freeway/archive/2013/03/30/chars_for_number.html