프로그래밍/DB, SQL, EF

[MSSQL] 'Order by'절에서 'case'문 사용하기

당근천국 2014. 9. 12. 16:00

동적쿼리를 덜 사용하기 위해서 이짓저짓하다 보면 끝 자락쯤에서 생기는 문제가 오더바이(Order by)절입니다.

오더바이절에서도 선택문을 제한적이지만 사용은 가능합니다.(몇 버전부터 가능한지는 모르겠습니다.)

(참고 : MSDN - ORDER BY 절(Transact-SQL))

 

연관글 영역

 

 

1. 사용 방법

사용 방법은 크게 2가지가 있습니다.

일반적인 케이스문처럼 사용하는 방법과 콤마(,)를 이용하여 여러 조건을 주는 것이죠.

Declare @nOrderColumn int = 1;

Select *
From tb_BigData1
Order by (case @nOrderColumn
			when 1 Then Data1
			when 2 Then Data2
			when 3 Then Data3
			when 4 Then Data4
			else nIndex
			End ) Desc

 

Declare @nOrderColumn int = 1;

Select *
From tb_BigData1
Order by Case When @nOrderColumn = 1 Then Data1 End Desc
			, Case When @nOrderColumn = 2 Then Data2 End Desc
			, Case When @nOrderColumn = 3 Then Data3 End Desc
			, Case When @nOrderColumn = 4 Then Data4 End Desc

 

 

 

2. 문제

위 코드는 겉으로만 말짱할 뿐 막상 사용하려면 몇 가지 문제점이 있습니다.

 

일반적인 'case'방법은 정렬 방향을 정할 수 없다는 것이고 여러 조건을 주는 방법은 비용이 많이 발생한다는 문제가 있습니다.

정렬 방향은 'case'로 사용할 수 없다.

 

조건이 1개 늘어날 때마다 비용이 증가한다.

 

 

3. 문제 해결

결국 정렬 방향이 고정이면 일반적인 'case'문 사용 방법을 사용하는 것이 좋고, 비용을 무시해도 된다면 여러 조건을 주는 방법이 좋습니다.

 

그! 러! 나!

어느 정도 두 마리 토끼를 잡고 싶다고 하시면 두 가지 방법을 혼합하는 방법이 있습니다.

Select *
From tb_BigData1
Order by case When  @nSort <> 1 And @nSort <> 2
				Then nIndex end Desc
		, case when @nSort = 1
				Then (Case @nOrderColumn
						When 1 Then Data1
						When 2 Then Data2
						When 3 Then Data3
						When 4 Then Data4
						Else nIndex
						End) end Asc
		, case when @nSort = 2
				Then (Case @nOrderColumn
						When 1 Then Data1
						When 2 Then Data2
						When 3 Then Data3
						When 4 Then Data4 
						Else nIndex
						End) end Desc

 

 

정렬 방향은 2가지에 예외까지 해서 3가지이니 정렬 방향을 이용하여 조건의 개수를 줄여 성능을 확보하는 방법입니다.

동적쿼리를 들어가지 않으나....중복코드가 있다는 문제점은 있지만 적당한 성능과 정확한 동작을 보여줍니다.

 

 

위 코드는 '@nSort <> 1 And @nSort <> 2'를 많이 쓰니까 이렇게 하면 성능이 좋지 않을까 해서 이렇게 해둔 것인데 좀 더 간결하게 만들고 싶다면 아래와 같이 하셔도 됩니다.

Select *
From tb_BigData1
Order by case when @nSort = 1
				Then (Case @nOrderColumn
						When 1 Then Data1
						When 2 Then Data2
						When 3 Then Data3
						When 4 Then Data4
						Else nIndex
						End) end Asc
		, case when @nSort <> 1
				Then (Case @nOrderColumn
						When 1 Then Data1
						When 2 Then Data2
						When 3 Then Data3
						When 4 Then Data4
						Else nIndex
						End) end Desc

 

 

마무리

 

결국 혼합방식을 쓰는 것까지는 좋은데 이전에도 문제가 됐던 'Case'문이 또 문제를 일으킨 셈입니다.

(참고 : [MSSQL] MSSQL의 페이징 쿼리 고찰 - 1. Row_Number + bettwen)

 

일반적인 언어라면 첫 번째 조건이 맞으면 다음 조건들을 무시되어야 하는데 'case'문은 상황에 따라서 뒷 문장이 무시되거나 검사되는 것 같습니다.

그런데 '여러 조건을 주는 방법'에 같은 조건을 여러 개 넣어도 맨 처음 맞은 조건 1개만 동작합니다.

결국 쓸데없이 자원을 낭비하고 있다는 소리입니다-_-;;;

 

좀 더 테스트를 해봐야 알겠지만 좀 이해할 수 없는 동작이네요.