
2024년 10월 7일
category의 PK가 books테이블의 FK가 됨
books 테이블 설정




그런데, category테이블의 name을 가져오면 book의 name인지, cateogry의 name인지 알 수 없음 -> AS 이용해서 별칭 지어주기

그렇다고 해서 테이블의 필드가 바뀌는 것은 아님 : 오해no. just 별칭
그런데, 굳이 별칭을 사용해서 다른 곳에서 사용할 필요는 없음 → * 을 쿼리에서 쓰지 못함.
그럼 컬럼 하나하나 다 말해줘야함 → 테이블의 칼럼 이름을 그냥 바꾸는게 나음




// BookController.js
const bookDetail = (req, res) => {
  let { id } = req.params;
  id = parseInt(id);
  let sql = `SELECT * FROM books LEFT JOIN category
  ON books.category_id = category.id WHERE books.id = ?`;
  conn.query(sql, id, (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();
    }
  });
};POSTMAN_ GET+localhost:9999/1

시간 범위에 따라서 신간 도서 보여주기
데이터 더 넣어주고

데이터베이스 시간 범위 구하기




최근 한달 이내 : 신간으로 범위 설정해서 선택
SELECT * FROM books WHERE pub_date BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW();


// BookController.js
const conn = require("../mariadb"); // db 모듈
const { StatusCodes } = require("http-status-codes"); // status code 모듈
const allBooks = (req, res) => {
  let { category_id, news } = req.query;
  let sql = "SELECT * 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, news];
  } 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()";
    values = news;
  }
  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();
    }
  });
};
POSTMAN) GET + localhost:9999/books?category_id=0

POSTMAN) GET + localhost:9999/books?category_id=0&news=true

: 선택한 개수 만큼 도서를 뿌려주고 다음 페이지로 넘어가도록 하기
페이징 : 몇개씩 보여줄까?
ex) SELECT * FROM books; → 전체 도서 리스트 100개
… 8개씩  필요하면 ?
… 4개씩 필요하면 ?
→ 한페이지에 데이터를 뿌려 줄 수 있는 만큼만 전달 하겠다는 의미
워크벤치에서 실습 먼저 해보자
SELECT * FROM books LIMIT (숫자) OFFSET (숫자)
 ex) SELECT * FROM books LIMIT 3 OFFSET 3; (2번째 페이지 3개 보겠다)
ex) SELECT * FROM books LIMIT 3 OFFSET 3; (2번째 페이지 3개 보겠다) ex) SELECT  FROM books LIMIT 5 OFFSET 5; (2번째 페이지 5개 보겠다)
ex) SELECT  FROM books LIMIT 5 OFFSET 5; (2번째 페이지 5개 보겠다)

LIMIT과 OFFSET을 더 간단하게 쓸 수 있음 → 순서가 바뀜
SELECT * FROM books LIMIT 8, 4; (위와 같은 결과임)

// BookController.js
const conn = require("../mariadb"); // db 모듈
const { StatusCodes } = require("http-status-codes"); // status code 모듈
// (카테고리별, 신간 여부) 전체 도서 목록 조회
const allBooks = (req, res) => {
  let { category_id, news, limit, currentPage } = req.query;
  // limit: page당 도서 수 ex. 3
  // currentPage: 현재 몇 페이지 ex. 1, 2, 3 ...
  // offset: 첫페이지니깐 0부터 시작하고, 두번째 페이지는 3부터 시작, 세번째 페이지는, 6 -> 0, 3, 6, 9, 12...
  // offset = limit * (currentPage-1)
  let offset = limit * (currentPage - 1);
  let sql = "SELECT * FROM books LIMIT ? OFFSET ?";
  let values = [limit, offset];
  if (category_id && news) {
    sql +=
      " WHERE category_id = ? AND pub_date BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW()";
    values = [...values, category_id, news];
  } else if (category_id) {
    sql += " WHERE category_id = ?";
    values = [...values, category_id];
  } else if (news) {
    sql +=
      " WHERE pub_date BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW()";
    values = [...values, news];
  }
  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();
    }
  });
};POSTMAN) GET + localhost:9999/books?limit=4¤tPage=1

400 에러 발생

 콘솔창 에러를 보면,
숫자가 문자열로 들어가 있어서임 ⇒ let values= [parseInt(limit), offset]; 으로 고쳐야함 & offset은 이미 계산을 해줘서 숫자로 변환됨
let offset = limit * (currentPage - 1);
  let sql = "SELECT * FROM books LIMIT ? OFFSET ?";
  let values = [parseInt(limit), offset];POSTMAN) GET + localhost:9999/books?limit=4¤tPage=1

POSTMAN) GET + localhost:9999/books?limit=4¤tPage=2

POSTMAN) GET + localhost:9999/books?limit=4¤tPage=0&news=true

신간만 보려고 위처럼 url을 입력했더니 에러가 나왔다.
에러를 잡아보자
코드를 봤을때 sql의 순서와 다른 것들도 봐야함
일단, value에는 news가 들어갈 필요 없기 때문에 다 빼준다 → news는 true값으로 sql문에 영향력을 끼칠 일이 없음
LIMIT과 OFFSET이 sql문에서 앞으로 오면 에러가 나기 때문에 바꿔 줘야함 ⇒ WHERE 절이 앞에 있어야함
순서가 잘 맞게 들어갔을 때

순서가 잘못 들어갔을 때

// BookController.js
const conn = require("../mariadb"); // db 모듈
const { StatusCodes } = require("http-status-codes"); // status code 모듈
// (카테고리별, 신간 여부) 전체 도서 목록 조회
const allBooks = (req, res) => {
  let { category_id, news, limit, currentPage } = req.query;
  let offset = limit * (currentPage - 1);
  let sql = "SELECT * FROM books";
  let values = []; // sql문을 보면 category_id가 먼저 들어와야하니깐
									 // limit과 offset을 나중에 적어준다
  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 = [...values, 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();
    }
  });
};POSTMAN) GET + localhost:9999/books?limit=4¤tPage=1

POSTMAN) GET + localhost:9999/books?limit=4¤tPage=2

POSTMAN) GET + localhost:9999/books?limit=4¤tPage=1&news=true

POSTMAN) GET + localhost:9999/books?limit=4¤tPage=1&category_id=0

🍏🍎 오늘의 느낀점 : 오늘은 도서 목록 조회에 대한 전반적인 내용을 배웠다. JOIN 쿼리를 통해 두 테이블을 합쳐서 데이터를 보여주고, 페이징을 백엔드에서 구현하는 방법을 배웠다. 예전에 일할때 페이징 작업에 대해서 어떻게 이루어지는건지 궁금했었는데 이런 방식으로 프론트와 주고 받으면서 페이징을 구현하는거구나 하는 것을 알았다. 연습 필요!!