DB/Oracle
코딩테스트 : SQL STUDY 기록
sujinbang
2025. 5. 28. 19:14
1. GROUP BY / HAVING
-- [프로그래머스] 그룹별 조건에 맞는 식당 목록 출력하기
-- 리뷰를 가장 많이 작성한 회원의 리뷰
-- 조회 : 회원이름, 리뷰텍스트, 리뷰작성일
-- 정렬 : 리뷰작성일 오름, 리뷰텍스트 오름
SELECT T1.MEMBER_NAME, T2.REVIEW_TEXT
, TO_CHAR(T2.REVIEW_DATE, 'YYYY-MM-DD') AS REVIEW_DATE
FROM MEMBER_PROFILE T1
INNER JOIN REST_REVIEW T2
ON T1.MEMBER_ID = T2.MEMBER_ID
INNER JOIN (
SELECT MEMBER_ID
FROM REST_REVIEW
GROUP BY MEMBER_ID
HAVING COUNT(REVIEW_ID) = (
-- 서브쿼리: 최대 리뷰 수 찾기
SELECT MAX(CNT)
FROM (
SELECT COUNT(REVIEW_ID) AS CNT
FROM REST_REVIEW
GROUP BY MEMBER_ID
))
) T3
ON T1.MEMBER_ID = T3.MEMBER_ID
ORDER BY REVIEW_DATE, REVIEW_TEXT
2. CASE WHEN 조건 THEN 결과
-- [프로그래머스] 조건별로 분류하여 주문상태 출력하기
-- Oracle의 조건문(decode, case when)
-- Oracle에서 쌍따옴표와 홑따옴표 구분
-- (')홑따옴표 : 문자열을 감싸주는 기호
-- (")쌍따옴표 : 컬럼명 등을 감싸주는 기호
-- 컬럼명을 쓸때는 쌍따옴표, 문자열은 홑따옴표 !
SELECT ORDER_ID, PRODUCT_ID, TO_CHAR(OUT_DATE, 'YYYY-MM-DD') AS OUT_DATE,
(CASE WHEN TO_CHAR(OUT_DATE, 'YYYY-MM-DD') <= '2022-05-01' THEN '출고완료'
WHEN TO_CHAR(OUT_DATE, 'YYYY-MM-DD') > '2022-05-01' THEN '출고대기'
ELSE '출고미정'
END) AS "출고여부"
FROM FOOD_ORDER
ORDER BY ORDER_ID
3. JOIN
- INNER JOIN : 중복 제거
- OUTER JOIN : 전체 다 출력
- LEFT JOIN : 왼쪽만 전체 다 출력
- RIGHT JOIN : 오른쪽만 전체 다 출력
-- [프로그래머스] 조건에 부합하는 중고거래 댓글 조회하기
-- 2022년 10월
-- 조회 : 게시글제목, 게시글ID, 댓글 ID, 댓글작성자 ID, 댓글 내용, 댓글 작성
SELECT T1.TITLE, T1.BOARD_ID, T2.REPLY_ID, T2.WRITER_ID, T2.CONTENTS
, TO_CHAR(T2.CREATED_DATE, 'YYYY-MM-DD') AS "CREATED_DATE"
FROM USED_GOODS_BOARD T1
INNER JOIN USED_GOODS_REPLY T2
ON T1.BOARD_ID = T2.BOARD_ID
WHERE TO_CHAR(T1.CREATED_DATE, 'YYYY-MM') = '2022-10'
ORDER BY TO_CHAR(T2.CREATED_DATE, 'YYYY-MM-DD'), TITLE
4. UNION / UNION ALL
- UNION : 중복 제거
- UNION ALL : 중복 허용
-- [프로그래머스] 오프라인/온라인 판매 데이터 통합하기
-- 2022년 3월의 오프라인/온라인 상품 판매 데이터
-- > SALES_DATE
-- 조회 : 판매 날짜, 상품ID, 유저ID, 판매량
-- OFFLINE_SALE 판매 데이터의 USER_ID, NULL로 표시
-- 정렬 : 판매일 오름, 상품 ID 오름, 유저 ID 오름
SELECT *
FROM (
SELECT TO_CHAR(SALES_DATE, 'YYYY-MM-DD') AS SALES_DATE, PRODUCT_ID, USER_ID, SALES_AMOUNT
FROM ONLINE_SALE
WHERE TO_CHAR(SALES_DATE, 'YYYYMM') = '202203'
UNION ALL
SELECT TO_CHAR(SALES_DATE, 'YYYY-MM-DD') AS SALES_DATE, PRODUCT_ID, NULL AS USER_ID, SALES_AMOUNT
FROM OFFLINE_SALE
WHERE TO_CHAR(SALES_DATE, 'YYYYMM') = '202203'
)
ORDER BY SALES_DATE, PRODUCT_ID, USER_ID
5. DUAL 테이블
임시 테이블을 생성할 때 사용
- Select 열 추가
- UNION ALL은 행 추가
SELECT 1 as "test"
, 3 as "test2"
FROM dual
UNION ALL
SELECT 2 as "test"
, 4 as "test2"
FROM dual
6. 서브쿼리
스칼라 서브쿼리(Select)
-- 사용 예시
SELECT D.DEPTNO, (SELECT MIN(EMPNO) FROM EMP WHERE DEPTNO = D.DEPTNO) as EMPNO
FROM DEPT D
ORDER BY D.DEPTNO
-- 출처: https://inpa.tistory.com/entry/MYSQL-📚-서브쿼리-정리 [Inpa Dev 👨💻:티스토리]
SELECT 절 서브쿼리는 데이터의 양이 많을수록 실행속도가 느려지기 때문에 거의 사용되지 않는 명령어
인라인 뷰 (From)
쿼리를 하나의 테이블로 사용
SELECT *
FROM (
SELECT '1997-08-22' as "생년월일", 'SJBANG' as "닉네임"
from dual
UNION ALL
SELECT '1999-01-20' as "생년월일", 'BEST' as "닉네임"
from dual
UNION ALL
SELECT '1998-10-02' as "생년월일", 'GOOD' as "닉네임"
from dual
UNION ALL
SELECT '1994-11-12' as "생년월일", 'GREATE' as "닉네임"
from dual
)
WHERE SUBSTR(생년월일, 0, 4) = '1997'
Where 서브쿼리
-- CATEGORY별 제일 비싼 : MAX()
-- 조회 : 식품의 분류, 가격, 이름
-- 조건 : 식품분류 IN (과자, 국, 김치, 식용유)
-- 정렬 : 가격 내림
SELECT CATEGORY, PRICE, PRODUCT_NAME
FROM FOOD_PRODUCT
WHERE CATEGORY IN ('과자', '국', '김치', '식용유')
AND PRICE IN (
SELECT MAX(PRICE)
FROM FOOD_PRODUCT
GROUP BY CATEGORY
)
ORDER BY PRICE DESC
7. SUBSTR / LIKE
- SUBSTR
-- 위 테이블에서 생년월일이 1997년인 데이터만 출력
SELECT *
FROM (
SELECT '1997-08-22' as "생년월일", 'SJBANG' as "닉네임"
from dual
UNION ALL
SELECT '1999-01-20' as "생년월일", 'BEST' as "닉네임"
from dual
UNION ALL
SELECT '1998-10-02' as "생년월일", 'GOOD' as "닉네임"
from dual
UNION ALL
SELECT '1994-11-12' as "생년월일", 'GREATE' as "닉네임"
from dual
)
WHERE SUBSTR(생년월일, 0, 4) = '1997'
- LIKE '%%'
-- [프로그래머스] 특정 옵션이 포함된 자동차 리스트 구하기
-- '네비게이션' 옵션이 포함된 자동차 리스트
-- 정렬 : 자동차 ID 내림
SELECT *
FROM CAR_RENTAL_COMPANY_CAR
WHERE OPTIONS LIKE '%네비게이션%'
ORDER BY CAR_ID DESC