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