직접 DB 스키마를 설계하고 테이블을 만들어 단순히 read나 insert 하는 쿼리가 아닌 정말로 화면 상에서 데이터를 불러오기 위한 쿼리를 작성하는 경험을 통해 정말 많이 배운 것 같습니다. 특히 join 개념을 조금 더 알게 된 것 같아 굉장히 뿌듯한 실습이었습니다.
야놀자를 선정하여 이번 실습 프로젝트를 진행하였습니다.
다음과 같이 ER 다이어그램을 구성했습니다.
데이터그램 설계 pdf 문서
데이터그램 설계 png
DB 스키마 설계 및 데이터 포함 엑셀 파일
작성한 쿼리문은 다음 10개입니다. 사용자로부터 입력을 받을 값들은 SET로 미리 지정했습니다.
SET @conditionStart := '2021-10-27 18:00:00', @conditionEnd := '2021-10-28 10:00:00';
SELECT
roomName,
roomShortInfo,
IF((room.bSookbak=1 and DATEDIFF(@conditionStart, @conditionEnd)=-1),dayPrice,timePrice) AS roomPrice,
roomRemainCnt,
defaultPersonCnt,
maxPersonCnt
FROM room
INNER JOIN reservation ON room.roomIdx = reservation.roomIdx
INNER JOIN roomprice r on room.roomIdx = r.roomIdx
WHERE
reserveStatus='active'
AND
(@conditionStart >= reservation.reserveEnd
OR
@conditionEnd <= reservation.reserveStart)
GROUP BY room.roomIdx;
바로 안 떠올라서 고민을 많이 했었지만 조금 생각해 보면 알 수 있었습니다. 예약 정보는 reservation 테이블에 저장되어 있으니, 방들을 쭉 조회해서 사용자가 원하는 숙박 시작 날짜와 끝 날짜에 대해서 사용자의 예약 시작 날짜 >= 예약 정보의 끝 OR 사용자의 예약 끝 날짜 <= 예약 정보의 시작
이면 겹치는 예약 없이 방들을 조회할 수 있었습니다.
SET @couponIdx := 1;
SELECT
roomName,
roomShortInfo,
IF((room.bSookbak=1 and DATEDIFF(@conditionStart, @conditionEnd)=-1),dayPrice,timePrice) AS roomPrice,
roomRemainCnt,
defaultPersonCnt,
maxPersonCnt
FROM room
INNER JOIN reservation ON room.roomIdx = reservation.roomIdx
INNER JOIN roomprice r on room.roomIdx = r.roomIdx
INNER JOIN couponavaillist c on room.roomIdx = c.roomIdx
WHERE
reserveStatus='active'
AND
c.couponIdx = @couponIdx
AND
(@conditionStart >= reservation.reserveEnd
OR
@conditionEnd <= reservation.reserveStart)
GROUP BY room.roomIdx;
1번의 연장선입니다. 각 쿠폰 적용이 가능한 숙소 couponAvailList를 참조하여 방 목록을 조회합니다.
SET @memberIdx := 2, @couponIdx := 1, @companyIdx := 3, @roomIdx := 7,
@reserveType := '0', @reserveStart := '2021-10-19 18:00:00', @reserveEnd := '2021-10-19 21:00:00';
INSERT INTO reservation
(memberIdx, couponIdx, companyIdx, roomIdx, price, reserveType, reserveStart, reserveEnd)
VALUES(
@memberIdx,
@couponIdx,
@companyIdx,
@roomIdx,
(SELECT IF(@reserveType=1, dayPrice, timePrice)
*IFNULL(1-discountRate*0.01, 1)
-IFNULL(discountprice, 0) FROM roomprice
INNER JOIN couponavaillist as couponavail on roomprice.roomIdx = couponavail.roomIdx
INNER JOIN coupon as coupon on couponavail.couponIdx = coupon.couponIdx
WHERE couponavail.roomIdx=@roomIdx and couponavail.couponidx=@couponIdx),
@reserveType,
@reserveStart,
@reserveEnd)
방마다 적용 가능한 할인 쿠폰 인덱스를 입력 받아 할인을 적용한 값을 reservation 테이블에 삽입하였습니다.
SET @memberIdx := 3, @companyIdx := 3, @roomIdx := 7, @reserveIdx := 9, @rating := 4.5, @reviewDescription := '재방문 의사 있어요~';
INSERT INTO review
(memberIdx, companyIdx, roomIdx, reserveIdx, rating, reviewDescription, reviewReply)
VALUES
(@memberIdx, @companyIdx, @roomIdx, @reserveIdx, @rating, @reviewDescription, null);
평범한 INSERT INTO ~ VALUES ~ 구문입니다.
SET @reviewIdx := 6, @reviewReply := '감사합니다!! 더욱 노력하는 업장이 되도록 하겠습니다!!';
UPDATE review
SET reviewReply = @reviewReply
WHERE reviewIdx = @reviewIdx;
점주 버전 어플리케이션을 사용해보지 않아 잘 모르지만, 고객들이 남긴 리뷰를 보고 reply를 단다면 reviewIdx로 조회 및 업데이트 할 것이라 생각했습니다.
SET @companyIdx := 3;
SELECT roomName, roomCategory, memberNick, rating, reviewDescription, reviewReply, createdDate
FROM review
INNER JOIN company c on review.companyIdx = c.companyIdx
INNER JOIN room r on review.roomIdx = r.roomIdx
INNER JOIN member m on review.memberIdx = m.memberIdx
WHERE c.companyIdx=@companyIdx;
이용객의 닉네임, 리뷰 별점, 리뷰와 점주 답글, 방 기본 정보와 리뷰 날짜를 반환합니다.
SELECT companyName, companyRating, minPrice, companyReviewCnt, companyImageUrl
FROM company
INNER JOIN reservation r on company.companyIdx = r.companyIdx
INNER JOIN companyimagelist c on company.companyIdx = c.companyIdx
GROUP BY companyName
HAVING COUNT(companyName) > 0
ORDER BY COUNT(companyName) DESC
LIMIT 5;
리뷰 테이블에서 가장 많이 기록된 5개의 숙소의 이름, 평균 별점, 최소 금액, 리뷰 갯수, 대표 사진 썸네일을 가져옵니다.
SELECT companyName, companyRating, minPrice, companyReviewCnt, companyImageUrl
FROM company
INNER JOIN companyimagelist c on company.companyIdx = c.companyIdx
INNER JOIN likelist l on company.companyIdx = l.companyIdx
GROUP BY l.companyIdx
HAVING COUNT(l.companyIdx) > 0
ORDER BY COUNT(l.companyIdx) DESC
LIMIT 5;
멤버별 찜한 숙소 정보를 저장하는 likelist 테이블에서 group by로 정렬하여 찜 수가 많은 숙소를 내림차순으로 5개 가져옵니다.
SET @companyIdx='2';
SELECT ownerName, businessName, ownerAddress, ownerEmail, ownerPhoneNumber, businessNumber
FROM companyowner
INNER JOIN company c on companyowner.companyIdx = c.companyIdx
WHERE c.companyIdx=@companyIdx;
숙소 판매자 정보가 기록된 CompanyOwner 테이블에서 해당 정보를 읽어옵니다.
SET @searchCondition='서울특별시';
SELECT companyName, companyRating, companyReviewCnt, availTimeStart, minPrice, category, companyImageUrl
FROM company
INNER JOIN location l on company.locationIdx = l.locationIdx
INNER JOIN companyimagelist c on company.companyIdx = c.companyIdx
WHERE (l.cityInfo=@searchCondition OR l.provinceInfo=@searchCondition);
검색어 중 하나라도 도 정보 / 시,군,구 정보와 일치하는 경우 company 정보를 읽어옵니다.
RDBMS : Relational DataBase Management System 입니다. 관계형 모델을 기반으로 하는 데이터베이스 관리 시스템 유형입니다. 관계형 모델이란, 실제 세계의 데이터를 관계 (Relation)라는 개념을 사용해 표현하는 데이터 모델입니다. 예를 들어 사과를 좋아하는 사람 A가 있다고 합시다. 그렇다면 A와 사과는 관계가 있고, 이는 곧 'A가 사과를 좋아한대' 라는 데이터가 됩니다. 이런 형태의 데이터를 저장하기 위한 관리시스템이 바로 RDBMS입니다.
SQL : Structured Query Language입니다. RDBMS의 데이터를 관리하기 위해 설계된 특수 목적의 프로그래밍 언어입니다.
DataBase 용어 : RDB 기준으로 작성하였습니다.
유일성과 최소성 : https://moonibot.tistory.com/61를 참고하였습니다.
키
1:1 관계 / 1:N관계 / N:M관계 : 개념이 이해하는데 좀 어려워서 헤맸었는데, 정리하고 보니 딱 하나로 귀결 될 수 있을 것 같습니다.
테이블의 같은 컬럼에 해당 값이 여러 개 존재할 수 있는가?
테이블의 한 컬럼에 FK로 다른 릴레이션을 참조한다고 할 때, 해당 외래키가 여러개 존재할 수 있으면 N관계에 속합니다.
사람 A가 좋아하는 과일에 대한 정보를 다음 테이블 PersonFruitList 테이블로 저장한다고 하면,
id | 사람 이름 | 좋아하는 과일(의 기본키) |
---|---|---|
1 | A | 사과 |
2 | A | 귤 |
3 | B | 오렌지 |
... | ... | ... |
과일 정보는 Fruit 테이블에 저장되어 있다고 합시다.
알아보기 쉽게 사과, 귤, 오렌지라고 적었지만 각각에 해당하는 기본키가 FK로 참조되어 있다면 설계에 따라 다음과 같이 경우가 나뉩니다.
1) Person과 Fruit 테이블이 1:1 관계를 가질 때 :
PersonFruitList에는 A라는 사람이 하나, 과일도 하나가 들어와야 합니다. 즉 서로 다른 사람은 서로 다른 과일을 좋아해야 하고 한 사람 당 하나의 과일 밖에 좋아하지 못합니다.
2) Person과 Fruit 테이블이 1:N 관계를 가질 때 :
PersonFruitList에 A라는 사람이 하나 들어와야 하는 건 동일합니다. 하지만 서로 다른 사람도 같은 과일을 좋아할 수 있습니다. 즉 사과를 서로 다른 여러 사람이 좋아할 수 있습니다.
3) PersonFruitList와 Fruit 테이블이 N:M 관계를 가질 때 :
PersonFruitList에 A 뿐만 아니라 모든 사람이 여러 개의 과일을 좋아할 수 있습니다. 동일한 사람 정보도 여러 개 들어올 수 있으며, 동일한 과일 정보도 여러 개 들어올 수 있습니다. 이제야 세상이 평화로워졌네요 🧐
추가적으로 알아보면 좋을 SQL 함수