ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 인기 페이지 구현(좋아요 수 많은 이미지 차례대로 출력)
    데이터베이스/쿼리 2021. 11. 17. 15:22

    인기페이지를 구현하려고 한다.

    인기페이지란, 좋아요 수가 많은 이미지를 차례대로 출력해 화면에 보여주는 페이지이다.

     

    상황 설명을 하겠다.

    현재 사이트에 가입한 user 는 총 3명이다. (user = 1,2,3 존재)

     

    지금 로그인한 user =1 이다.

    user 1은,

    user 2 의 이미지(A)에 좋아요를 눌렀고,

    user 3의 이미지(B)에도 좋아요를 눌렀다.

     

    그런데 user2 역시 user 3의 이미지(B) 에 좋아요를 눌러서,

    결과적으로

     

    좋아요 수는

    user 2의이미지(A) : 1

    user 3의 이미지(B) : 2

    가 된다.

     

    따라서 user1 의 인기페이지에는

    B ,A 순으로 화면에 나타나게 된다. 

     

    이를 직접 쿼리로 구현해야 한다.

     

     

    먼저 image db는

    이와 같은 칼럼으로 이루어져 있고,

     

    likes db는 아래와 같은 칼럼으로 이루어져 있다.

     

    즉 우리는 최종적으로 likes db의 좋아요 수를 계산하여, 이 조건이 적용된

    image db 의 값들을 가져올 것이다. 

     

    그럼 쿼리를 만들어 보겠다.

     

     

    # 쿼리 1

    SELECT * FROM image;

    일단 image db를 확인해본다.

     

     

    그러면 이렇게 이미지 2개가 나온다.

    첫번째 이미지(id=1)는 위에서 설명한 user 2 의 이미지 (A)이고,

    두번째 이미지(id=2) 는 위에서 설명한 user 3의 이미지(B)이다.

     

     

    # 쿼리 2

    SELECT * FROM likes;

    likes db를 확인해본다.

     

    첫번째와 세번째 id를 보면, imageId =2 즉 user 3의 이미지(B)를

    userId = 1,2 가 좋아요 하고 있음을 알 수 있다.

     

    두번째 id를 보면, imageId=1 즉, user 2의 이미지(A)를 user 1가 좋아요 하고 있음을 알 수 있다.

     

    # 쿼리 3

    SELECT imageId, COUNT(imageId) likeCount FROM likes GROUP BY imageId;

    COUNT(imageId) 한 결과를 likeCount 칼럼에 나타낸다.

    COUNT(imageId)란, imageId 개수를 세어서 즉, 위의 쿼리 결과에서, imageId =1, 2 각각의 개수를 센다는 것.

     

    즉, 

    imageId=1 일 때 userId 는 1로, 결과값이 1개 있으므로 좋아요 수( likeCount)는 1이다.

    imageId =2 일 때 userId가 1,2 로 결과값이 2개 있으므로 likeCount는 2이다.

     

     

    이것을 GROUP BY imageId

    즉, imageId 순서대로 정렬해서 나타내면 쿼리 결과가 나온다.

     

     

    이렇게 결과가 나온다.

     

    # 쿼리 4

    SELECT * 
    FROM image i INNER JOIN (SELECT imageId, COUNT(imageId) likeCount FROM likes GROUP BY imageId) c
    ON i.id = c.imageId;

    여기서 INNER JOIN 을 볼 수 있다.

    INNER JOIN 괄호 안에 있는 쿼리는

    쿼리 3이다.

     

    이 쿼리문은, 

     

     

    1) SELECT * : 즉 모든 값을 가져와라,

     

    2) FROM image i :  image db 데이터 값과 (image db 별칭 : i )

     

    3) INNER JOIN (SELECT imageId, COUNT(imageId) likeCount FROM likes GROUP BY imageId) c

    : 쿼리 3에서 나온 결과값 중 (결과값의 별칭 : c)

     

     

    4) ON i.id = c.imageId;

    : image db 에서 imageId 값과

    쿼리 3의 결과에서 imageId 값이 같은 것들의 값을 가져오라는 뜻

     

    즉, 쿼리 1에서 image db를 보면,

     

     

    이렇게 imageId = 1,2 가 있다.

    그러면 쿼리 3의 결과값 중 

     

    여기서 imageId =1 ,2 를 만족하는 값(여기서는 다른 이미지가 없으므로 모든 값들을 말함)을 가져오면

     

    이렇게, imageId 가 같은

    image db의 결과값과 쿼리 3의 결과값이 이어붙여져서 같이 나오게 된다.

     

     

     

     

     

     

     

     

    INNER JOIN

    참고 자료 : https://gent.tistory.com/376

     

     

    # 쿼리 5

     

    SELECT * 
    FROM image i INNER JOIN (SELECT imageId, COUNT(imageId) likeCount FROM likes GROUP BY imageId) c
    ON i.id = c.imageId
    ORDER BY likeCount DESC;

    likeCount값에 대해서 내림차순해서 화면에 이미지를 나타낼 것이므로,

    즉 좋아요 수가 많은 이미지가 위에 나오도록

    ORDER BY 를 이용해서 내림차순 정렬한다.

     

    결과값:

     

    그런데, 우리는 그냥 image db 의 데이터만 있으면 되지, 쿼리 3의 결과값은 필요 없으므로,

    이를 지워내도록한다.

    (쿼리 3은 image db의 데이터들을 정렬해서 나타내는데에만 쓰이지,

    화면에 이미지를 출력할 때 쓰이지 않으므로 )

     

    # 쿼리 6

     

    SELECT i.* 
    FROM image i INNER JOIN (SELECT imageId, COUNT(imageId) likeCount FROM likes GROUP BY imageId) c
    ON i.id = c.imageId
    ORDER BY likeCount DESC;

    결과:

     

    이렇게 쿼리 3의 결과, 즉 imageId, likeCount 가 사라졌다.

     

    --------------

    이 쿼리를 Repository.java에서 nativeQuery를 이용해서 사용하면 된다.

     

     

     

     

     

     

     

    참고 자료 : 이지업 강의 사이트 "스프링부트 SNS 프로젝트 - 포토그램 만들기"

    댓글

Designed by Tistory.