Search
🧺

Oracle, Mysql에서 IN절 순서와 동일하게 정렬하고 싶을 때

작성일
2020/10/12 00:00
수정일
카테고리
데이터베이스
태그
Oracle
목표 : Oracle에서 In절에 들어가는 순서대로 출력 순서를 정하는 방법을 알아본다
현재 회사에선 iBatis를 SQL Mapper로 활용하고 있다. IN절에 파라미터를 전달하고, 그 순서대로 Order by를 시켜야 할 일이 있었다.
간단할 거 같은데?? 하면서 접근했는데 쉽지 않았다.
MYSQL에서는 FIND\_IN\_SET() 혹은 FIELD() Function을 사용한 트릭으로 구현이 가능하다.
SELECT * FROM your_table WHERE id IN (5,2,6,8,12,1) ORDER BY FIELD(id,5,2,6,8,12,1);
SQL
복사
혹은,
SELECT * FROM your_table WHERE id IN (5,2,6,8,12,1) ORDER BY FIND_IN_SET(id,'5,2,6,8,12,1');
SQL
복사
MySQL FIELD, FIND__SET 공식문서
하지만 해당 함수와 동일한 기능을 하는 함수가 ORACLE엔 없었다
함수를 집적 구현하는 방법까지 소개되어있었지만..
닭잡는 일에 소잡는 칼을 쓰는 격 아닌가?? 게다가 DB에 내맘대로 함수 선언하면 혼난다
가열차게 구글링에 박차를 올려서 방법을 찾아냈다.
오라클 조건함수 DECODE를 활용하여!
참고로 DECODE는 다음과 같은 오라클 조건 함수이다.
DECODE(비교할 칼럼이름, A일 때, A수행 , B일때, B수행... , 나머지)
나머지값을 안 주면 맞는 조건이 없을 때 NULL이 된다. 업무 볼 때 참 많이 마주치는 친구이다.
SELECT * FROM your_table WHERE id IN ('가', '나', '다', '라') ORDER BY DECODE(id,'가',1,'나',2,'다',3,'라',4);
SQL
복사
이런 방식으로, IN절 순서와 동일하게 부여할 수 있다!
SqlMapper에 list를 보내주고, DECODE(id ... ) 에서 ... 부분에 값과 인덱스를 iterate 시켜주면 되겠다!
회사가 사용하는 SqlMapper가 Mybatis였더라면 foreach로 뚝딱 쉽게 해결했을 것이다.
참고로 index가 문자열로 들어가면 숫자 오름차순으로 정렬이 안 될때가 있으니, $으로 바인드하셔라
-- MyBatis 라면 SELECT * FROM your_table ORDER BY DECODE(id, <foreach collection="seqList" item="item" index="index" separator="," close=")"> #{item}, ${index} </foreach>
SQL
복사
그러나.. 우리 회사는 iBatis를 쓰고 있고 MyBatis에 foreach에 해당하는 iterator에는 index가 없다
그래서 index에 해당하는 자료구조를 추가로 맵핑해서 보내려고 했는데, iterator블록 안에선 두개 이상의 프로펄티를 한번에 쓸 수 없다...
그래서! 다음 포스팅에서는 iBatis Iterator블록에서 두개이상의 프로펄티를 활용하는 법을 알아보겠다!
21년 11월 13일에 블로그 이전하면서 다시 보다가..^^
당시에 일하던 회사에선 SQL에서 대부분의 로직을 처리(Smart DAO)하는 연통 배관형 구조(Stovepiping)를 활용했습니다. 그래서 다소 복잡한 로직을 모두 SQL로 처리했었는데요. (롤업, 큐브, 파티션 바이, 유니온 등이 난무했던 것으로 기억합니다)
현재는 SQL에서 모든 비즈니스 로직을 처리하는 것보다, DAO는 데이터 입출력의 역할만 맡기고 복잡한 비즈니스 로직은 도메인을 담당하고 있는 Service Layer에서 처리해주는 것이 맞다고 생각합니다. SQL에서 모든 것을 처리하는 것은 1회용(ad-hoc) 쿼리를 양산하여 로직의 중복을 일으켜 유지보수성을 떨어뜨리기 때문입니다.