Oracle, Tibero에서 group by와 order by를 같이 쓰는 방법

smallcherry's techlog·2023년 6월 30일
0

간만의 삽질 기록

내가 구현하고자 한 것

내가 구현하고자 한 것은 아래와 같다.

SELECT SEARCH_LOG.QUERY
FROM SEARCH_LOG
WHERE SEARCH_LOG.member_id = 5
GROUP BY SEARCH_LOG.QUERY
ORDER BY SEARCH_LOG.search_time DESC;

간단하다. search_log에서 query라는 검색어를 중복없이, search time의 내림차순으로 조회하려 했다.
결론적으로 Oracle 베이스의 Tibero를 사용 중인 우리 팀 프로젝트에서는 먹히지 않는 쿼리문이었다..

참고로 이 쿼리문은 Mysql에서는 valid하다고 한다. 구글링을 할때는 항상 DBMS이름을 함께 구글링 하는 습관을 기르자..

  • 해당 글에서 query는 쿼리가 아닌 "검색어"의 의미로 사용된 컬럼 명임을 주의!!

문제 해결 과정

1. 쿼리 메서드 이용 with Distinct

처음에는 팀에서 사용 중인 기술 스택이 Hibernate라서 SpringDataJpa에서 제공하는 쿼리 메서드를 이용하여 해당 쿼리를 작성하려 했는데, findDistinctQueryBy...로 찾으려 했지만, 검색어 query가 단순 string 데이터였고 distinct는 내 생각과 다르게 entity단위로만 동작한다는 문제가 있었다.
엔티티 코드에서 필드로 엔티티를 가지는 경우, DB 상에는 해당 필드 엔티티의 아이디가 외래키로 저장되는데, 그러한 경우만 Distinct로 걸러낼 수 있는 것이다.

  1. Distinct 사용이 유효한 경우 -> Query를 저장하는 별도 "QUERY" 엔티티가 있는 상황
@Entity
public class SearchLog{
	/*중략*/
	private Query query;
}
  1. 내 경우 -> 단순 String 데이터이기 때문에 Distinct가 적용되지 않는다
@Entity
public class SearchLog{
	/*중략*/
	private String query;
}

2. JPQL이용, GROUP BY절 사용

그래서 GROUP BY를 통해 QUERY 컬럼 중심으로 그루핑을 한 후, ORDER BY 절로 검색 시간 최신 순으로 정렬하여 데이터를 반환하고자 했다.
그런데 내가 원하는 데이터를 생각하거 쓰고 싶은대로 쿼리를 쓰고 돌려보니, ORDER BY에서 에러가 났다.

order기준이 group by안에 있지 않다는 것이다..! (이러한 제약은 ORACLE 계열 sql에만 있다고 한다.)

3. 먹힌 방법 : GROUP BY절에 집계 함수 사용

구글링 결과, Oralce(및 오라클 문법을 늘 따라가는 Tibero)에서는
GROUP BY 절에 의해 distinct하지 않은 값은 ORDER BY의 대상이 될 수 없다.

일단 member_id = 5인 전체 SEARCH_LOG 데이터는 아래와 같다.

GROUP BY절에 사용 된 Query 기준으로 보았을 때, "iu"라는 검색어가 다른 SEARCH_TIME을 가지게 된다. 이런 경우가 바로 GROUP BY절에 의해 distinct하지 않은 케이스 인 것이다.

따라서, query에 의해 distict도록 집계 함수로 SEARCH_TIME을 감싸준 아래 쿼리는 말이 된다.

같은 검색기록 중에서도 최근에 검색된 것을 MAX함수로 한번 필터링을 한 후에, 그를 기준으로 DESC 정렬을 하니 최신순 정렬이 된다!

profile
Java Developer

0개의 댓글

관련 채용 정보