SQLパズル:文字列中の重複する文字を削除する
元ネタはこちら↓
文字列中の重複する文字を削除する - ミックのブログ
こんな感じ?で書いてみた↓
with odai as( /* @SQL Server 2005*/
/* お題 */
select word_key = 1, word_txt =’aaaaaa’ union all
select word_key = 2, word_txt =’abababab’ union all
select word_key = 3, word_txt =’abcdeaccc’ union all
select word_key = 4, word_txt =’abbcdeab’ union all
select word_key = 5, word_txt =’abcdefg’
)
,nn as(
/* 1~10の自然数 */
select num = 1 union all
select num = 2 union all
select num = 3 union all
select num = 4 union all
select num = 5 union all
select num = 6 union all
select num = 7 union all
select num = 8 union all
select num = 9 union all
select num = 10
) ,step1 as(
/* 縦展開 */
select word_key
, num
, txt = case num when 1 then substring(word_txt,1,1)
when 2 then substring(word_txt,2,1)
when 3 then substring(word_txt,3,1)
when 4 then substring(word_txt,4,1)
when 5 then substring(word_txt,5,1)
when 6 then substring(word_txt,6,1)
when 7 then substring(word_txt,7,1)
when 8 then substring(word_txt,8,1)
when 9 then substring(word_txt,9,1)
when 10 then substring(word_txt,10,1) end
from odai a
cross join nn
),step2 as(
/* 空白除去 */
select word_key
, num
, txt
from step1
where txt <>”
),step3 as(
–今まで出現した文字列(自分自身より左にある文字列群)を自己結合で横に並べる
select a.word_key
, na=a.num
, nb=b.num
, fa = a.txt
, fb = b.txt
from step2 a
inner join step2 b
on a.word_key = b.word_key
and a.num>= b.num
) ,step4 as(
/* 重複除去 */
select word_key
, na
, fa
, fb
,nt = count(fb)
from step3
where fa=fb
group by word_key
, na
, fa
, fb
having count(fb) = 1
) ,step5 as(
/* 再度横展開 */
select word_key
, f1 = max(case na when 1 then fa end )
, f2 = max(case na when 2 then fa end )
, f3 = max(case na when 3 then fa end )
, f4 = max(case na when 4 then fa end )
, f5 = max(case na when 5 then fa end )
, f6 = max(case na when 6 then fa end )
, f7 = max(case na when 7 then fa end )
, f8 = max(case na when 8 then fa end )
, f9 = max(case na when 9 then fa end )
, f10 = max(case na when 10 then fa end )
from step4
group by word_key
)
/* Q.E.D */
select word_key =word_key
, word_txt = isnull(f1,”)
+ isnull(f2,”)
+ isnull(f3,”)
+ isnull(f4,”)
+ isnull(f5,”)
+ isnull(f6,”)
+ isnull(f7,”)
+ isnull(f8,”)
+ isnull(f9,”)
+ isnull(f10,”)
from step5
...長くなってしまったorz
一応解説するとお題の文字列をいったん1文字1文字縦展開して1文字1レコードにしておいて、その文字の左に並んでいる文字列群を自己結合して横に表記した上で重複判定して、重複していないレコードだけに絞り込んでから再度横展開するみたいな感じのSQL文なのですが、正直言って確かにループ処理するほうが手っ取り早い。

