Contents

[-]
1 질문
2 풀이
3 한글 주의사항


초성, 중성, 종성은 이렇게 하면 된다.
select
    nm
,   nchar(part1)
,   nchar(part2)
,   nchar(part3)
from (
    select
	    nm
    ,	0x1100 + ((unicode(nm) - 0xAC00) / (21*28)) part1
    ,	0x1161 + ((unicode(nm) - 0xAC00) % (21*28)) / 28 part2
    ,	0x11A7 + ((unicode(nm) - 0xAC00) % 28) part3
    from (select '출' nm) t
) t

커뮤니티에 다음과 같은 질문이 올라왔다. 잼있을꺼 같아서 풀어봤다..

1 질문 #

ms sql 디비에서 고객 테이블의 이름 컬럼을 조사해서
가나다 별로 존재하는 데이터들의 공통된 첫 음소들을 따오려고 합니다.
예를 들어


김삼순
김호랭
금이빨

나가라
나와라
노랭이

라면빨
라이도

마파두부
모자장수

밥퍼요
밥줘요

.
.
.


이렇게 이름 데이터 있다면 


'가' 분류에는 '김''금' 두가지가 있으니까 공통된 형태소인 'ㄱ'이 결과로 나오고
'나' 분류에도 '나''노' 두가지가 있으니까 역시 공통된 형태소인 'ㄴ'이 결과로 나오고
'다' 분류에는 데이터가 없으니 '다' 항목에는 결과가 나오지 않고
'라' 분류에는 첫 글자가 모두 '라'로 일치하니 '라'가 결과로 나오고
'마' 분류에는 '마''모' 두가지가 있으니 'ㅁ' 이 나오고
'바' 분류에는 '밥'만 있으니 '밥' 이 결과로 나오고

.
.
.

이런 식으로 결과를 뽑으려면 어떻게 쿼리를 짜야 할까요...
여러분들의 고견을 듣고 싶습니다.
  • 원문은 -> [http]클릭(http://www.devpia.com/Maeul/Contents/Detail.aspx?BoardID=41&MAEULNO=17&no=7629&ref=7629&page=3)

2 풀이 #

with temp 
as
(
	select '김삼순' nm union all
	select '김호랭' union all
	select '금이빨' union all
	select '나가라' union all
	select '나와라' union all
	select '노랭이' union all
	select '라면빨' union all
	select '라이도' union all
	select '마파두부' union all
	select '모자장수' union all
	select '밥퍼요' union all
	select '밥줘요'
), part1(seq, part1)
as
(
	select 0, 'ㄱ' union all
	select 1, 'ㄲ' union all
	select 2, 'ㄴ' union all
	select 3, 'ㄷ' union all
	select 4, 'ㄸ' union all
	select 5, 'ㄹ' union all
	select 6, 'ㅁ' union all
	select 7, 'ㅂ' union all
	select 8, 'ㅃ' union all
	select 9,'ㅅ' union all
	select 10,'ㅆ' union all
	select 11,'ㅇ' union all
	select 12,'ㅈ' union all
	select 13,'ㅉ' union all
	select 14,'ㅊ' union all
	select 15,'ㅋ' union all
	select 16,'ㅌ' union all
	select 17,'ㅍ' union all
	select 18,'ㅎ'
), part2(seq, part2)
as
(
	select 0, 'ㅏ' union all
	select 1, 'ㅐ' union all
	select 2, 'ㅑ' union all
	select 3, 'ㅒ' union all
	select 4, 'ㅓ' union all
	select 5, 'ㅔ' union all
	select 6, 'ㅕ' union all
	select 7, 'ㅖ' union all
	select 8, 'ㅗ' union all
	select 9,'ㅘ' union all
	select 10,'ㅙ' union all
	select 11,'ㅚ' union all
	select 12,'ㅛ' union all
	select 13,'ㅜ' union all
	select 14,'ㅝ' union all
	select 15,'ㅞ' union all
	select 16,'ㅟ' union all
	select 17,'ㅠ' union all
	select 18,'ㅡ' union all
	select 19,'ㅢ' union all
	select 20,'ㅣ'
), part3(seq, part3)
as
(
	select 0, ''   union all
	select 1, 'ㄱ' union all
	select 2, 'ㄲ' union all
	select 3, 'ㄳ' union all
	select 4, 'ㄴ' union all
	select 5, 'ㄵ' union all
	select 6, 'ㄶ' union all
	select 7, 'ㄷ' union all
	select 8, 'ㄹ' union all
	select 9,'ㄺ' union all
	select 10,'ㄻ' union all
	select 11,'ㄼ' union all
	select 12,'ㄽ' union all
	select 13,'ㄾ' union all
	select 14,'ㄿ' union all
	select 15,'ㅀ' union all
	select 16,'ㅁ' union all
	select 17,'ㅂ' union all
	select 18,'ㅄ' union all
	select 19,'ㅅ' union all
	select 20,'ㅆ' union all
	select 21,'ㅇ' union all
	select 22,'ㅈ' union all
	select 23,'ㅊ' union all
	select 24,'ㅋ' union all
	select 25,'ㅌ' union all
	select 26,'ㅍ' union all
	select 27,'ㅎ'
), rs
as
(
	select
		nchar(part1) part1
	,	case when sum(part2)/count(*) = min(part2) then nchar(min(part2)) end part2
	,	case when 
				sum(part2)/count(*) = min(part2) 
			and sum(part3)/count(*) = min(part3) 
			then nchar(min(part3))
		end part3
	from (
		select
			nm
		,	0x1100 + ((unicode(nm) - 0xAC00) / (21*28)) part1
		,	0x1161 + ((unicode(nm) - 0xAC00) % (21*28)) / 28 part2
		,	0x11A7 + ((unicode(nm) - 0xAC00) % 28) part3
		from temp
	) t
	group by
		nchar(part1)
) 
select
	case 
		when a.part1 is not null and a.part2 is null and a.part3 is null
			then a.part1
		when a.part1 is not null and a.part2 is not null and a.part3 is null
			then nchar(0xAC00 + (b.seq*21*28)+(c.seq*28))
		when a.part1 is not null and a.part2 is not null and a.part3 is not null
			then nchar(0xAC00 + (b.seq*21*28)+(c.seq*28)+d.seq)
	end 결과
from rs a
	left join part1 b
		on a.part1 = b.part1
	left join part2 c
		on a.part2 = c.part2
	left join part3 d
		on a.part3 = d.part3

/*
결과
----
ᄀ
ᄂ
라
ᄆ
밥

(5개 행 적용됨)
*/

3 한글 주의사항 #

declare @a nvarchar(40);
set @a= N'支'
--set @a= N'ㅢ'

select 
    case when @a collate Latin1_General_CI_AS like '%[ㄱ-힇]%' then 1 else 0 end --결과: 0
,   case when @a collate Korean_Wansung_CI_AS like '%[ㄱ-힇]%' then 1 else 0 end --결과: 1, 한글로 like가 잘 안된다.