이번주 코테가 여러개 있어.. SQL 공부를 다시 하고 있다.
그 김에 팀프로젝트에서 알게 되었던 내용에 대해 다시 정리해 보았다.
🔧 SELECT DISTINCT 와 ORDER BY 가 함께 쓰이는 경우 정렬은 예상하지 못하게 일어난다
팀프로젝트를 하는데, 팀원 분의 쿼리에서 예상했던 결과가 나오지 않고 있었다.
나 역시 해당 쿼리로 해결 할 수 있을 거라 생각했는데 원하는 결과가 나오지 않았고, 이를 해결하는 과정에서 SELECT DISTINCT 와 ORDER BY 가 함께 쓰는 경우, 주의해야 함을 알게 되었다.
🔧 당시 상황
study - book 은 다대일 관계 ( study -> book 으로 book 의 pk 를 참조하고 있다 )
쿼리로 가져오려고 한 것 : 최근에 스터디가 생성된 책 목록을 가져오기
먼저, Study 테이블에 들어있는 데이터를 살펴보자.
최근에 스터디가 생성된 책 목록을 뽑아내고 싶다면 ( 당연히 , 이 책 목록역시 최신 생성 스터디 순으로 + 당연히 책은 중복 없이 )
위의 상태에서는 다음 id 순으로 book 이 출력될 것을 기대했다
2
1
4
3
그래서 이와 같은 쿼리를 작성했다
SELECT DISTINCT book.*
FROM book
INNER JOIN study on book.id = study.book_id
ORDER BY study.created_at DESC;
하지만 이 결과 출력되는 책의 순서는 2,1,3,4 였다
어떻게 이런 일이 발생한 걸까?
🔧주의 해야 하는 상황 : (MySQL)
MySQL 에서는 아래와 같이 “DISTINCT 키워드 가 붙은 컬럼” 과 “ORDER BY 의 기준이 되는 컬럼” 이 서로 다른 경우 주의해야 한다.
SELECT DISTINCT(col_1), ....
...
ORDER BY col_2 DESC
..;
MySQL 의 경우 위와 같은 상황이 "허용"되기에 주의해야 한다!
다른 DB 들에서는 이런식으로 order by 컬럼과, distinct 컬럼이 서로 다른 경우, 예외를 발생시킨다고 한다.
근데 mysql 에서는 그냥 실행시켜주고.. 이거 결과가 왜이래? 하게 되는 것 같다.
🔧 어떤 일이 발생하나?
이는 위의 쿼리가 처리 되는 "순서"에 의해 발생하는 상황이다.
- 우리의 기대: ORDER BY 가 먼저 일어나고 ->이렇게 정렬된 Study 와 book 을 join 한 결과에서 distinct 한 튜플들로 생성된 릴레이션이 나올 것
- 하지만, 실제로는 그냥 원본 테이블 상에서 가장 먼저 등장한 튜플을 DISTINCT 로 뽑아 낸 이후에 ORDER BY 를 하기 때문이다.
- 따라서, 우리가 원하는 튜플(레코드)이 뒤쪽에 등장했다면, 중복 제거된 상태로 추출한 데이터를 정렬하기에, 원하는 결과를 얻지 못하게 되는 것이었다.
'DB' 카테고리의 다른 글
카티션 곱, JOIN 에서 USING, ON / JOIN 에서 ON 과 WHERE (1) | 2022.10.31 |
---|---|
Database - "status" column을 갖는 것에 관하여 (0) | 2022.02.27 |