데이터베이스/쿼리

인기 페이지 구현(좋아요 수 많은 이미지 차례대로 출력)

have a good time 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 프로젝트 - 포토그램 만들기"