8-5 좋아요 API와 서브쿼리

airbus·2025년 3월 14일

프로그래머스

목록 보기
37/93

8-5 좋아요 API와 서브쿼리

좋아요 API

LikeController.js에서 좋아요 추가, 취소(제거)기능을 구현 모듈화하여 likes.js에서 연결하였습니다.

likes.js

// likes.js

const express = require('express');
const router = express.Router();
const {addLike, removeLike} = require('../controller/LikeController'); // 컨트롤러js에서 기능 받아옴

router.use(express.json());

// 좋아요 추가
router.post('/:id', addLike);

// 좋아요 취소/삭제
router.delete('/:id', removeLike);

module.exports = router;

LikeController.js

const conn = require('../../../../mariadb'); // maria db
const { StatusCodes } = require('http-status-codes'); // http status



// 좋아요 추가
const addLike = (req, res) => {

    const { id } = req.params;
    const { user_id } = req.body; // jwt가 없어서 임시로 body로 받아옴

    let sql = "INSERT INTO likes (user_id, liked_book_id) VALUES (?, ?)";
    let values = [user_id, id];
    conn.query(sql, values,
        (err, results) => {
            if (err) {
                console.log(err);
                return res.status(StatusCodes.BAD_REQUEST).end();
            }
            return res.status(StatusCodes.OK).json(results);
        })
};

// 좋아요 취소
const removeLike = (req, res) => {
    const { id } = req.params;
    const { user_id } = req.body; // jwt가 없어서 임시로 body로 받아옴

    let sql = "DELETE FROM likes WHERE user_id = ? AND liked_book_id = ?;";
    let values = [user_id, id];
    conn.query(sql, values,
        (err, results) => {
            if (err) {
                console.log(err);
                return res.status(StatusCodes.BAD_REQUEST).end();
            }
            return res.status(StatusCodes.OK).json(results);
        })
};


module.exports = {
    addLike,
    removeLike
};

Book API

mariaDB로 MySQLworkbench로 연동하여, 책 목록을 불러오는 API기능 중 좋아요(likes 테이블을 참고/기준으로) 여부를 판단하여 출력합니다(좋아요 개수만).

BookController.js

const conn = require('../../../../mariadb');
const { StatusCodes } = require('http-status-codes'); // http status

const allBooks = (req, res) => {
    let { category_id, news, limit, currentPage } = req.query;

    let offset = limit * (currentPage - 1);

    let sql = "SELECT *, (SELECT count(*) FROM likes WHERE books.id = liked_book_id) AS likes FROM books";

    let values = [];

    if (category_id && news) {
        sql += " WHERE category_id=? AND pub_date BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW()";
        values = [category_id]
    } else if (category_id) {
        sql += " WHERE category_id=?";
        values = [category_id]
    } else if (news) {
        sql += " WHERE pub_date BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW()"
    }

    sql += " LIMIT ? OFFSET ?";
    values.push(parseInt(limit), offset);


    conn.query(sql, values,
        (err, results) => {
            if (err) {
                console.log(err);
                return res.status(StatusCodes.BAD_REQUEST).end();
            }
            if (results.length)
                return res.status(StatusCodes.OK).json(results);
            else
                return res.status(StatusCodes.NOT_FOUND).end();
        })


}

const bookDetail = (req, res) => {
  
    let {user_id} = req.body;
    let book_id = req.params.id;

    sql = `SELECT *,
                    (SELECT count(*) FROM likes WHERE liked_book_id=books.id) AS likes,
                    (SELECT EXISTS (SELECT * FROM likes WHERE user_id = ? AND liked_book_id = ?)) AS liked
                FROM books
                LEFT JOIN category
                ON books.category_id = category.category_id
                WHERE books.id = ?;`;

    let values = [user_id, book_id, book_id]

    conn.query(sql, values,
        (err, results) => {
            if (err) {
                console.log(err);
                return res.status(StatusCodes.BAD_REQUEST).end();
            }
            if (results[0])
                return res.status(StatusCodes.OK).json(results[0]);
            else
                return res.status(StatusCodes.NOT_FOUND).end();
        })
}


module.exports = {
    allBooks,
    bookDetail,
}

보충

서브 쿼리

  • 쿼리안의 쿼리.
  • 쿼리안에서 특정 값을 반환하는 식의 조건식으로 사용됩니다.

count ()

  • 조건을 만족하는 행의 개수를 나타냅니다.

AS

  • 컬럼 별칭

likes 테이블 중 1번 책을 좋아요를 한 행 조회

SELECT * FROM likes WHERE liked_book_id = 1;

likes 테이블 중 1번 책을 좋아요를 한 행의 개수

SELECT count(*) FROM likes WHERE liked_book_id;

books의 테이블 전체조회

SELECT * FROM books;

books의 테이블 전체조회

SELECT *, (값) AS (새로 추가할 컬럼명) FROM books; // 값에는 조건을 입력

ex) SELECT *, (SELECT count(*) FROM likes WHERE books.id = liked_book_id) AS likes FROM books;

  • SELECT count(*) FROM likes likes 테이블에서 개수를 셉니다.
  • WHERE books.id = liked_book_id books 테이블의 id 값과 likes 테이블의 liked_book_id값이 일치하는 행의 수를 카운트합니다.
  • 그 결과를 'likes'이름의 칼럼으로 books테이블에 포함(추가)시켜 조회합니다.
    * liked_book_id 좋아요한 책의 id / books.id 책 id

likes

user_idliked_book_id
11
22
31

book

idtitle
1little book
2big book
3apple book

===> 좋아요 수를 반영하여 출력됩니다.

idtitlelikes
1little book2
2big book1
3apple book0


EXISTS

EXISTS를 사용하여 존재여부/= 사용자가 좋아요를 눌렀는지를 확인할 수 있습니다.

좋아요 여부

SELECT *,
 (SELECT EXISTS (SELECT * FROM likes WHERE user_id = 1 AND liked_book_id = 1)) AS liked
 FROM books WHERE books.id = 1;
  • (user_id 1번에 해당하는 사용자가)
  • books id가 1인 책의 좋아요를 눌렀는지
  • 눌렀으면 liked의 값은 1 / 누르지 않았으면 0

개수도 포함해서

SELECT *,
 (SELECT count(*) FROM likes WHERE liked_book_id=books.id) AS likes,
 (SELECT EXISTS (SELECT * FROM likes WHERE user_id = 1 AND liked_book_id = 1)) AS liked
 FROM books WHERE books.id = 8;

개별도서조회 sql join까지

SELECT *,
 (SELECT count(*) FROM likes WHERE liked_book_id=books.id) AS likes,
 (SELECT EXISTS (SELECT * FROM likes WHERE user_id = 1 AND liked_book_id = 1)) AS liked
 FROM books
 LEFT JOIN category
 ON books.category_id = category.id 
 WHERE books.id = 1;

서브쿼리를 사용하여 간단하게?.. 조건들을 추가하여 특정 값을 조회, 계산, 조건제한 등 원하는 값을 조회할 수 있다는 것을 알 수 있었습니다.

0개의 댓글