[MySQL8] UNION, Order by에 CASE WHEN 사용하기

Ericamoyed·2022년 1월 24일
0

개발한장

목록 보기
11/22

UNION

  • 알겠지만, 각 select들을 한 temp table로 합치는데 사용되는 친구다.
    (Select * from A where ~) UNION (Select * from B where ~) .. 요런식으로 쭉 사용 가능하다.
  • 하지만 temp table을 만드는 만큼, UNION 결과를 가지고 order by 나 group by를 했을 때 인덱스를 사용할수 없으므로 성능은 좋지 않다. 최대한 지양해야하는 친구
  • 겹치지 않는다는게 보장된다면, UNION (DISTINCT) 보다는 UNION ALL을 사용하는 것이 성능 상 좋다.
    • 왜냐하면 기본 UNION은 DISTINCT가 내장돼있는데, 요 operation을 위해 temp table의 모든 row에 대해 hash index를 생성하기 때문이다.
  • 나같은 경우는 UNION에 사용되는 각 Select 별로 order by 와 limit을 같이 사용해야하는 상황이었는데, 찾아보니 UNION의 각 Select 별 Order by는 효과가 없다는 이야기가 스택오버플로우에서 속속들이 찾아졌다.
    • 찾아보니 대부분 케이스는 '첫번째 Select order by에서 a로 정렬해서, <2, 3, 1> 순서고, 두번째 Select의 order by 에서 b로 정렬해서 <4, 6, 5> 등이 나왔는데, 둘 UNION을 시켰더니 <2, 3, 1, 4, 6, 5>가 아니에요!!' 와 같은 이야기라서 LIMIT이 붙으면 왠지 될것 같다는 그런 직감이 들었다.
    • 그래서 공식문서를 찾아봤다. 아니나 다를까! LIMIT과 함께 사용은 된다구 ㅎ
    • https://dev.mysql.com/doc/refman/8.0/en/union.html#union-order-by-limit
  • 여튼 이렇게 많이 리서치 했으나,, 역시 UNION은 아니라고 판단하여 다른 방식을 모색해서 해결했다.

CASE_WHEN IN ORDER BY

  • 대단한건 없고, 특정 케이스만 정렬을 다르게 해주세요 ㅠ 에 대한 대응책이 있다는 것이 메인 포인트다.
order by
	a.due_date desc ,
	CASE
		WHEN a.task_status != 'SERVICE'
		THEN a.sequence_no
		ELSE (-1 * a.sequence_no)
    END
    desc
  • a의 task_Status가 SERVICE가 아니라면 a.sequence_no로 desc 정렬, SERVICE라면 -a.sequence_no로 desc 정렬: 즉, sequence_no로 asc 정렬이라는 뜻.
  • 처음에 THEN, ELSE 로 desc, asc 설정도 바꿀수 있는줄 알고 넣었다가 (오류남..), desc, asc는 밖에서 한번만 사용할 수 있는걸 알게 되었다.
  • 따라서 desc, asc 대신 -1 곱한 값으로 같은 desc, asc를 사용하는 것으로 대체했다.
profile
꿈많은 개발자, 일상 기록을 곁들인

0개의 댓글