Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

일자별 판매량 차트 구현 시 판매량이 없는 일자 표시 방법 #58

Open
C-H-Kim opened this issue Jan 16, 2025 · 3 comments
Assignees
Labels
bug 빨.리.버.그.고.쳐 docs Project documentation

Comments

@C-H-Kim
Copy link
Contributor

C-H-Kim commented Jan 16, 2025

❓ 어떤 문제점인가?

일자별 차트를 구현할 때 시작일 ~ 종료일을 설정하면 각 일자와 해당 일자에 대한 총 판매량을 구해야했다.
하지만 단순히 일자로 GROUP BY를 하게 되면 총 판매량이 0인 경우의 일자를 얻을 수가 없었다.

image

2025-01-08부터 2025-01-14까지의 데이터를 판매일자(sales_date)로 그룹지어 조회하였지만
데이터가 없는 2025-01-11부터 2025-01-14까지는 조회되지 않았다.


📝 원인

GROUP BY의 동작 방식 때문이다. 없는 데이터에 관해서는 0으로 출력해주는 것이 아닌 조회 자체를 하지 않기 때문이다.


🔨 해결책은?

RECURSIVE CTE(Common Table Expression)을 사용하였다.
재귀 CTE 테이블로 해당 기간에 대한 일자 테이블 만들어줬고 이를 위에서 작성한 서브쿼리와 JOIN 하였다.

image image

이 두 테이블을 LEFT OUTER JOIN 하여 총 판매량이 없는 row에 대해서는 IFNULL을 사용해 0이 들어가도록 하였다.

image


❓ 왜 DB에서 처리하였는지?

Spring Boot에서 없는 일자에 대해 판매량을 0으로 넣어주어 새 리스트를 만들어도 됐지만 서버의 부담을 줄이고자 DB에서 SQL문으로 처리하였다.


‼️ 주의할 점

쿼리문에서 날짜를 비교할 때 부등호(<)를 사용했는데 MyBatis에서는 부등호 사용이 불가하여 아래와 같이 사용해야 한다.

기호 치환
> &gt
>= &gt=
< &lt
<= &lt=
@C-H-Kim C-H-Kim added bug 빨.리.버.그.고.쳐 docs Project documentation labels Jan 16, 2025
@C-H-Kim C-H-Kim self-assigned this Jan 16, 2025
@newbackjava
Copy link

오라클에서는 with절이라고 부르는 CTE는
선행된 쿼리를 정의해두고

후행하는 쿼리에서 쿼리를 재사용하는 기능을 말합니다.

서브쿼리로 만들어 사용할 수 있습니다.

SELECT DATE_ADD('2025-01-08', INTERVAL n.n DAY) AS dayOfWeek FROM ( SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 ) n WHERE DATE_ADD('2025-01-08', INTERVAL n.n DAY) <= '2025-01-14';

db 버전별 사용가능/불가능할 수 있습니다.
참고로 쿠팡 등에서는 with절과 CTE사용을 권장하고 있지 않습니다.
경력입사시험에서도 역시나 배제되어있습니다.

@C-H-Kim
Copy link
Contributor Author

C-H-Kim commented Jan 16, 2025

오라클에서는 with절이라고 부르는 CTE는 선행된 쿼리를 정의해두고

후행하는 쿼리에서 쿼리를 재사용하는 기능을 말합니다.

서브쿼리로 만들어 사용할 수 있습니다.

SELECT DATE_ADD('2025-01-08', INTERVAL n.n DAY) AS dayOfWeek FROM ( SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 ) n WHERE DATE_ADD('2025-01-08', INTERVAL n.n DAY) <= '2025-01-14';

db 버전별 사용가능/불가능할 수 있습니다. 참고로 쿠팡 등에서는 with절과 CTE사용을 권장하고 있지 않습니다. 경력입사시험에서도 역시나 배제되어있습니다.

MySQL에서도 잘 동작하네요 감사합니다! WITH절과 CTE 사용을 지양하도록 하겠습니다!

@newbackjava
Copy link

newbackjava commented Jan 16, 2025

<mapper namespace="com.example.mapper.UserMapper">
    <!-- 사용자 목록 조회 쿼리 -->
    <select id="getUsersByAge" parameterType="int" resultType="com.example.model.User">
       <![CDATA[
        SELECT *
        FROM users
        WHERE age > #{age}
       ]]>
    </select>
</mapper>

CDATA부분안에 넣어주면 태그로 인식하지 않습니다.^^

이 부분 안에 들어간 것은 다 char data로 인식하라는 의미!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 빨.리.버.그.고.쳐 docs Project documentation
Projects
None yet
Development

No branches or pull requests

2 participants