프로그래머스 SQL 고득점 Kit 정답 (Oracle)

KIMA·2025년 7월 16일

DB

목록 보기
11/11
post-thumbnail

이론은 다음 포스팅을 참고한다.
SELECT문으로 데이터 조회하기 (ORACLE)

SELECT문


Level 1

조건에 부합하는 중고거래 댓글 조회하기

SELECT
  b.TITLE,
  b.BOARD_ID,
  r.REPLY_ID,
  r.WRITER_ID,
  r.CONTENTS,
  TO_CHAR(r.CREATED_DATE, 'YYYY-MM-DD') AS CREATED_DATE
FROM
  USED_GOODS_BOARD b
JOIN
  USED_GOODS_REPLY r
ON
  b.BOARD_ID = r.BOARD_ID
WHERE
  TO_CHAR(b.CREATED_DATE, 'YYYYMM') = '202210'
ORDER BY
  r.CREATED_DATE ASC, b.TITLE ASC
  • 게시글이 2022년 10월에 작성 : TO_CHAR(b.CREATED_DATE, 'YYYYMM') = '202210'
  • 댓글 작성일자 출력 포맷을 YYYY-MM-DD으로 맞추기 : TO_CHAR(r.CREATED_DATE, 'YYYY-MM-DD')
    • 포맷을 맞추지 않으면 DATE 타입이라도 YYYY-MM-DD HH:MI:SS 형태로 출력된다.

과일로 만든 아이스크림 고르기

SELECT A.FLAVOR
FROM FIRST_HALF A
JOIN ICECREAM_INFO B
ON A.FLAVOR = B.FLAVOR
WHERE A.TOTAL_ORDER > 3000
  AND B.INGREDIENT_TYPE = 'fruit_based'
ORDER BY A.TOTAL_ORDER DESC

흉부외과 또는 일반외과 의사 목록 출력하기

SELECT
  DR_NAME,
  DR_ID,
  MCDP_CD,
  TO_CHAR(HIRE_YMD, 'YYYY-MM-DD') AS HIRE_YMD
FROM
  DOCTOR
WHERE
  MCDP_CD IN ('CS', 'GS')
ORDER BY
  HIRE_YMD DESC,
  DR_NAME ASC;
  • 진료과가 흉부외과(CS)이거나 일반외과(GS)인 의사 조회 : MCDP_CD IN ('CS', 'GS')
  • 고용일자 출력 포맷을 YYYY-MM-DD으로 맞추기 : TO_CHAR(HIRE_YMD, 'YYYY-MM-DD')
    • 포맷을 맞추지 않으면 DATE 타입이라도 YYYY-MM-DD HH:MI:SS 형태로 출력된다.

Level 2

3월에 태어난 여성 회원 목록 출력하기

SELECT MEMBER_ID, MEMBER_NAME, GENDER, TO_CHAR(DATE_OF_BIRTH, 'YYYY-MM-DD') AS DATE_OF_BIRTH
FROM MEMBER_PROFILE
WHERE TO_CHAR(DATE_OF_BIRTH, 'MM') = '03' AND GENDER = 'W' AND TLNO IS NOT NULL
ORDER BY MEMBER_ID
  • 3월 출생 : TO_CHAR(DATE_OF_BIRTH, 'MM') = '03'
    • 월 조건에서 비교 값은 항상 03처럼 0이 포함된 두 자리 문자열이어야 함에 유의한다.
  • 생년월일 출력 포맷을 YYYY-MM-DD으로 맞추기 : TO_CHAR(DATE_OF_BIRTH, 'YYYY-MM-DD')
    • 포맷을 맞추지 않으면 DATE 타입이라도 YYYY-MM-DD HH:MI:SS 형태로 출력된다.

재구매가 일어난 상품과 회원 리스트 구하기

SELECT USER_ID, PRODUCT_ID
FROM ONLINE_SALE
GROUP BY USER_ID, PRODUCT_ID
HAVING COUNT(*) > 1
ORDER BY USER_ID ASC, PRODUCT_ID DESC;
  • 2번 이상 구매(재구매)한 경우만 추출 : HAVING COUNT(*) > 1

조건에 맞는 개발자 찾기

SELECT ID, EMAIL, FIRST_NAME, LAST_NAME
FROM DEVELOPERS
WHERE SKILL_CODE & (SELECT CODE FROM SKILLCODES WHERE NAME = 'Python')
   OR SKILL_CODE & (SELECT CODE FROM SKILLCODES WHERE NAME = 'C#')
ORDER BY ID;
  • 개발자가 주어진 스킬 중 하나를 보유하고 있는지 확인 : WHERE SKILL_CODE & CODE

부모의 형질을 모두 가지는 대장균 찾기

SELECT C.ID, C.GENOTYPE, P.GENOTYPE AS PARENT_GENOTYPE
FROM ECOLI_DATA C
JOIN ECOLI_DATA P ON C.PARENT_ID = P.ID
WHERE C.GENOTYPE & P.GENOTYPE = P.GENOTYPE
ORDER BY C.ID;
  • 대장균이 부모의 형질을 모두 가지는지 확인 : WHERE C.GENOTYPE & P.GENOTYPE = P.GENOTYPE

업그레이드 된 아이템 구하기

SELECT C.ITEM_ID, C.ITEM_NAME, C.RARITY
FROM ITEM_INFO A
JOIN ITEM_TREE B ON A.ITEM_ID = B.PARENT_ITEM_ID
JOIN ITEM_INFO C ON B.ITEM_ID = C.ITEM_ID
WHERE A.RARITY = 'RARE'
ORDER BY C.ITEM_ID DESC;

특정 물고기를 잡은 총 수 구하기

SELECT COUNT(*) AS FISH_COUNT
FROM FISH_INFO F
JOIN FISH_NAME_INFO N ON F.FISH_TYPE = N.FISH_TYPE
WHERE N.FISH_NAME IN ('BASS', 'SNAPPER');
  • 특정 물고기에 속하는지 확인 : N.FISH_NAME IN ('BASS', 'SNAPPER')
  • 조건에 맞는 모든 행의 개수 계산 : COUNT(*)

Level3

대장균들의 자식의 수 구하기

SELECT A.ID, COUNT(B.ID) AS CHILD_COUNT
FROM ECOLI_DATA A
LEFT JOIN ECOLI_DATA B ON A.ID = B.PARENT_ID
GROUP BY A.ID
ORDER BY A.ID;
  • 0개의 자식을 가진 개체도 표시하기 위해 LEFT JOIN 사용
  • NULL 값은 COUNT에서 자동으로 제외됨 : COUNT(B.ID)

대장균의 크기에 따라 분류하기 1

SELECT ID,
       CASE 
           WHEN SIZE_OF_COLONY <= 100 THEN 'LOW'
           WHEN SIZE_OF_COLONY <= 1000 THEN 'MEDIUM'
           ELSE 'HIGH'
       END AS SIZE
FROM ECOLI_DATA
ORDER BY ID;
  • 프로그래밍 언어의 if-else문과 유사한 역할 : CASE WHEN 조건문

대장균의 크기에 따라 분류하기 2

SELECT ID,
       CASE 
           WHEN NTILE(4) OVER (ORDER BY SIZE_OF_COLONY DESC) = 1 THEN 'CRITICAL'
           WHEN NTILE(4) OVER (ORDER BY SIZE_OF_COLONY DESC) = 2 THEN 'HIGH'
           WHEN NTILE(4) OVER (ORDER BY SIZE_OF_COLONY DESC) = 3 THEN 'MEDIUM'
           ELSE 'LOW'
       END AS COLONY_NAME
FROM ECOLI_DATA
ORDER BY ID;
  • 데이터를 N개의 동일한 크기 그룹으로 분할하는 함수 : NTILE(N)

Level4

오프라인/온라인 판매 데이터 통합하기

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
  • 오프라인과 온라인 데이터 합치기 : UNION ALL (중복 제거 X, 성능 우수)
  • 오프라인 테이블에 없는 컬럼을 NULL로 명시 : NULL AS USER_ID
  • 판매일이 2022년 3월 : TO_CHAR(SALES_DATE, 'yyyymm') = '202203'
  • 판매일 출력 포맷을 yyyy-mm-dd으로 맞추기 : TO_CHAR(SALES_DATE, 'yyyy-mm-dd') AS SALES_DATE
    • 포맷을 맞추지 않으면 DATE 타입이라도 YYYY-MM-DD HH:MI:SS 형태로 출력된다.

SUM, MAX, MIN


Level 2

가격이 제일 비싼 식품의 정보 출력하기

SELECT PRODUCT_ID, PRODUCT_NAME, PRODUCT_CD, CATEGORY, PRICE
FROM FOOD_PRODUCT
WHERE PRICE = (SELECT MAX(PRICE) FROM FOOD_PRODUCT);

최솟값 구하기

SELECT MIN(DATETIME)
FROM ANIMAL_INS;
  • 가장 먼저 들어온 동물의 날짜 : MIN(DATETIME)

동물 수 구하기

SELECT COUNT(*) AS COUNT
FROM ANIMAL_INS;
  • 동물의 전체 마릿수 : COUNT(*)

조건에 맞는 아이템들의 가격의 총합 구하기

SELECT SUM(PRICE) AS TOTAL_PRICE
FROM ITEM_INFO
WHERE RARITY = 'LEGEND'

연도별 대장균 크기의 편차 구하기

  1. 윈도우 함수 사용 O

    SELECT EXTRACT(YEAR FROM DIFFERENTIATION_DATE) AS YEAR, 
        MAX(SIZE_OF_COLONY) OVER(PARTITION BY EXTRACT(YEAR FROM DIFFERENTIATION_DATE)) - SIZE_OF_COLONY AS YEAR_DEV,
        ID
    FROM ECOLI_DATA
    ORDER BY YEAR, YEAR_DEV
  2. 윈도우 함수 사용 X

    SELECT E.YEAR,
        M.MAX_SIZE_OF_COLONY - E.SIZE_OF_COLONY AS YEAR_DEV,
        E.ID
    FROM (
        SELECT ID, SIZE_OF_COLONY, EXTRACT(YEAR FROM DIFFERENTIATION_DATE) AS YEAR
        FROM ECOLI_DATA
    ) E
    JOIN (
        SELECT EXTRACT(YEAR FROM DIFFERENTIATION_DATE) AS YEAR, MAX(SIZE_OF_COLONY) AS MAX_SIZE_OF_COLONY
        FROM ECOLI_DATA
        GROUP BY EXTRACT(YEAR FROM DIFFERENTIATION_DATE)
    ) M ON E.YEAR = M.YEAR
    ORDER BY E.YEAR, YEAR_DEV

LEVEL 3

물고기 종류 별 대어 찾기

SELECT F.ID, N.FISH_NAME, F.LENGTH
FROM FISH_INFO F
JOIN FISH_NAME_INFO N ON F.FISH_TYPE = N.FISH_TYPE
WHERE (F.FISH_TYPE, F.LENGTH) IN (
    SELECT FISH_TYPE, MAX(LENGTH)
    FROM FISH_INFO
    GROUP BY FISH_TYPE
)
ORDER BY F.ID;
  • 복합 조건 서브쿼리 : (컬럼1, 컬럼2) IN (SELECT 컬럼1, 컬럼2 ...)

GROUP BY

Level 2

진료과별 총 예약 횟수 출력하기

SELECT MCDP_CD AS "진료과코드",
       COUNT(*) AS "5월예약건수"
FROM APPOINTMENT
WHERE TO_CHAR(APNT_YMD, 'YYYY-MM') = '2022-05'
GROUP BY MCDP_CD
ORDER BY "5월예약건수", "진료과코드";
  • 행 개수 계산 : COUNT(*)
  • 5월 예약 : TO_CHAR(APNT_YMD, 'YYYY-MM') = '2022-05'

성분으로 구분한 아이스크림 총 주문량

SELECT I.INGREDIENT_TYPE, SUM(TOTAL_ORDER) AS TOTAL_ORDER
FROM FIRST_HALF H
JOIN ICECREAM_INFO I ON H.FLAVOR = I.FLAVOR
GROUP BY I.INGREDIENT_TYPE
ORDER BY TOTAL_ORDER 
  • ORDER BY 절에 alias 사용 가능

조건에 맞는 사용자와 총 거래금액 조회하기

SELECT CAR_TYPE, 
       SUM(CASE WHEN OPTIONS LIKE '%통풍시트%' 
                  OR OPTIONS LIKE '%열선시트%' 
                  OR OPTIONS LIKE '%가죽시트%' 
                THEN 1 
                ELSE 0 
           END) AS CARS
FROM CAR_RENTAL_COMPANY_CAR
GROUP BY CAR_TYPE
ORDER BY CAR_TYPE;
  • '통풍시트', '열선시트', '가죽시트' 중 하나 이상의 옵션이 포함된 자동차 : OPTIONS LIKE '%통풍시트%' OR ... 혹은 REGEXP_LIKE(OPTIONS, '통풍시트|열선시트|가죽시트')
  • 특정 조건을 만족하는 행 수 : SUM(CASE WHEN ... THEN 1 ELSE 0 END)

고양이와 개는 몇 마리 있을까

SELECT ANIMAL_TYPE, COUNT(*) AS count
FROM ANIMAL_INS 
WHERE ANIMAL_TYPE IN ('Cat', 'Dog')
GROUP BY ANIMAL_TYPE
ORDER BY ANIMAL_TYPE

동명 동물 수 찾기

SELECT NAME, COUNT(*) AS COUNT
FROM ANIMAL_INS 
WHERE NAME IS NOT NULL
GROUP BY NAME
HAVING COUNT(*) >= 2
ORDER BY NAME

Level 3

부서별 평균 연봉 조회하기

SELECT D.DEPT_ID, D.DEPT_NAME_EN, ROUND(AVG(SAL), 0) AS AVG_SAL
FROM HR_DEPARTMENT D
JOIN HR_EMPLOYEES E ON D.DEPT_ID = E.DEPT_ID
GROUP BY D.DEPT_ID, D.DEPT_NAME_EN
ORDER BY AVG_SAL DESC
  • 평균연봉은 소수점 첫째 자리에서 반올림 : ROUND(AVG(SAL), 0)

특정 조건을 만족하는 물고기별 수와 최대 길이 구하기

SELECT COUNT(*) AS FISH_COUNT, 
       MAX(NVL(LENGTH, 10)) AS MAX_LENGTH, 
       FISH_TYPE
FROM FISH_INFO
GROUP BY FISH_TYPE
HAVING AVG(NVL(LENGTH, 10)) >= 33
ORDER BY FISH_TYPE;
  • 10cm이하의 물고기들은 10cm로 취급하여 평균 길이를 구하기 : AVG(NVL(LENGTH, 10))

조건에 맞는 사용자와 총 거래금액 조회하기

SELECT U.USER_ID, U.NICKNAME, SUM(B.PRICE) AS TOTAL_SALES
FROM USED_GOODS_BOARD B
JOIN USED_GOODS_USER U ON B.WRITER_ID = U.USER_ID
WHERE B.STATUS = 'DONE'
GROUP BY U.USER_ID, U.NICKNAME
HAVING SUM(B.PRICE) >= 700000
ORDER BY TOTAL_SALES;

대여 횟수가 많은 자동차들의 월별 대여 횟수 구하기

SELECT 
  EXTRACT(MONTH FROM START_DATE) AS MONTH,
  CAR_ID,
  COUNT(*) AS RECORDS
FROM 
  CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE
  CAR_ID IN (
    SELECT CAR_ID
    FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
    WHERE TO_CHAR(START_DATE, 'yyyymm') BETWEEN '202208' AND '202210'
    GROUP BY CAR_ID
    HAVING COUNT(*) >= 5
  )
  AND TO_CHAR(START_DATE, 'yyyymm') BETWEEN '202208' AND '202210'
GROUP BY 
  EXTRACT(MONTH FROM START_DATE), CAR_ID
ORDER BY 
  MONTH ASC, CAR_ID DESC;
  • 날짜에서 월만 추출(8월 -> 8) : EXTRACT(MONTH FROM START_DATE)
  • 대여 시작날짜가 8월~10월 : TO_CHAR(START_DATE, 'yyyymm') BETWEEN '202208' AND '202210'
  • 행 개수 계산 : COUNT(*)

자동차 대여 기록에서 대여중 / 대여 가능 여부 구분하기

SELECT CAR_ID,
       MAX(CASE WHEN TO_DATE('2022-10-16', 'YYYY-MM-DD') 
                      BETWEEN START_DATE AND END_DATE 
                THEN '대여중' 
                ELSE '대여 가능' 
           END) AS AVAILABILITY
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
GROUP BY CAR_ID
ORDER BY CAR_ID DESC;
  • 2022-10-16이 대여 기간 내에 존재하는지 확인 : TO_DATE('2022-10-16', 'YYYY-MM-DD') BETWEEN START_DATE AND END_DATE
  • MAX('대여중', '대여가능') : 사전 순으로 큰 값인 대여중 반환
  • 문자열을 DATE 타입으로 변환 : TO_DATE('2022-10-16', 'YYYY-MM-DD')

즐겨찾기가 가장 많은 식당 정보 출력하기

SELECT FOOD_TYPE, REST_ID, REST_NAME, FAVORITES
FROM REST_INFO
WHERE (FOOD_TYPE, FAVORITES) IN (
    SELECT FOOD_TYPE, MAX(FAVORITES)
    FROM REST_INFO
    GROUP BY FOOD_TYPE
)
ORDER BY FOOD_TYPE DESC;

카테고리 별 도서 판매량 집계하기

SELECT B.CATEGORY AS CATEGORY, SUM(S.SALES) AS TOTAL_SALES
FROM BOOK_SALES S
JOIN BOOK B ON S.BOOK_ID = B.BOOK_ID
WHERE TO_CHAR(S.SALES_DATE, 'yyyymm') = '202201'
GROUP BY B.CATEGORY
ORDER BY B.CATEGORY
  • 2022년 1월에 판매된 도서 : WHERE TO_CHAR(S.SALES_DATE, 'yyyymm') = '202201'

Level4

년, 월, 성별 별 상품 구매 회원 수 구하기

SELECT EXTRACT(YEAR FROM S.SALES_DATE) AS YEAR, 
       EXTRACT(MONTH FROM S.SALES_DATE) AS MONTH, 
       U.GENDER AS GENDER, 
       COUNT(DISTINCT U.USER_ID) AS USERS
FROM ONLINE_SALE S
JOIN USER_INFO U ON S.USER_ID = U.USER_ID
WHERE U.GENDER IS NOT NULL
GROUP BY EXTRACT(YEAR FROM S.SALES_DATE), 
         EXTRACT(MONTH FROM S.SALES_DATE), 
         U.GENDER
ORDER BY YEAR, MONTH, GENDER

JOIN


Level2

조건에 맞는 도서와 저자 리스트 출력하기

SELECT B.BOOK_ID AS BOOK_ID, A.AUTHOR_NAME AS AUTHOR_NAME, TO_CHAR(B.PUBLISHED_DATE, 'yyyy-mm-dd') AS PUBLISHED_DATE
FROM BOOK B
JOIN AUTHOR A ON B.AUTHOR_ID = A.AUTHOR_ID
WHERE B.CATEGORY = '경제'
ORDER BY PUBLISHED_DATE

Level3

없어진 기록 찾기

SELECT O.ANIMAL_ID, O.NAME
FROM ANIMAL_OUTS O
LEFT JOIN ANIMAL_INS I ON O.ANIMAL_ID = I.ANIMAL_ID
WHERE I.ANIMAL_ID IS NULL
ORDER BY O.ANIMAL_ID

Level4

방법1. INNER JOIN

SELECT *
FROM (
    SELECT A.FLAVOR
    FROM FIRST_HALF A
    JOIN (
        SELECT FLAVOR, SUM(TOTAL_ORDER) AS TOTAL_ORDER
        FROM JULY
        GROUP BY FLAVOR
    ) B ON A.FLAVOR = B.FLAVOR
    ORDER BY (A.TOTAL_ORDER + B.TOTAL_ORDER) DESC
)
WHERE ROWNUM <= 3

방법2. UNION ALL

SELECT FLAVOR
FROM (
    SELECT FLAVOR
    FROM (
        SELECT FLAVOR, TOTAL_ORDER
        FROM FIRST_HALF
        UNION ALL
        SELECT FLAVOR, TOTAL_ORDER
        FROM JULY
    )
    GROUP BY FLAVOR
    ORDER BY SUM(TOTAL_ORDER) DESC
)
WHERE ROWNUM <= 3;

String, Date


Level1

자동차 대여 기록에서 장기/단기 대여 구분하기

SELECT HISTORY_ID, CAR_ID, TO_CHAR(START_DATE, 'yyyy-mm-dd') AS START_DATE, TO_CHAR(END_DATE, 'yyyy-mm-dd') AS END_DATE, CASE WHEN (END_DATE - START_DATE + 1) >= 30 THEN '장기 대여' ELSE '단기 대여' END AS RENT_TYPE
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
WHERE TO_CHAR(START_DATE, 'yyyymm') = '202209'
ORDER BY HISTORY_ID DESC
  • 대여일수 : END_DATE - START_DATE + 1

Level2

DATETIME에서 DATE로 형 변환

SELECT ANIMAL_ID, NAME, TO_CHAR(DATETIME, 'yyyy-mm-dd') AS 날짜
FROM ANIMAL_INS 
ORDER BY ANIMAL_ID

자동차 평균 대여 기간 구하기

SELECT CAR_ID, TO_CHAR(ROUND(AVG(END_DATE - START_DATE + 1), 1), 'FM9999990.0') AS AVERAGE_DURATION
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
GROUP BY CAR_ID
HAVING AVG(END_DATE - START_DATE + 1) >= 7
ORDER BY ROUND(AVG(END_DATE - START_DATE + 1), 1) DESC, CAR_ID DESC;
  • 평균 대여 기간은 소수점 두번째 자리에서 반올림 : ROUND(AVG(END_DATE - START_DATE + 1), 1)
  • 평균 대여 기간 .0 형식으로 출력 : `TO_CHAR(평균대여기간, 'FM9999990.0')
    • 9 : 숫자가 있으면 표시, 없으면 공백(소수부에서는 공백 대신 0)
    • 0 : 숫자가 없으면 0으로 강제 출력
    • FM : Fill Mode, 앞뒤 공백 제거
  • AVERAGE_DURATION으로 정렬하면, 문자열 정렬되므로 조심

카테고리 별 상품 개수 구하기

SELECT SUBSTR(PRODUCT_CODE, 1, 2) AS CATEGORY, COUNT(*) AS PRODUCTS
FROM PRODUCT 
GROUP BY SUBSTR(PRODUCT_CODE, 1, 2) 
ORDER BY CATEGORY

이름에 el이 들어가는 동물 찾기

SELECT ANIMAL_ID, NAME
FROM ANIMAL_INS
WHERE ANIMAL_TYPE = 'Dog' AND UPPER(NAME) LIKE '%EL%'
ORDER BY NAME

조건에 부합하는 중고거래 상태 조회하기

SELECT
    BOARD_ID
    , WRITER_ID
    , TITLE
    , PRICE    
    , CASE STATUS
        WHEN 'SALE' THEN '판매중'
        WHEN 'RESERVED' THEN '예약중'
        WHEN 'DONE' THEN '거래완료'
    END STATUS
FROM USED_GOODS_BOARD
WHERE CREATED_DATE = TO_DATE('2022-10-05', 'yyyy-mm-dd')
ORDER BY BOARD_ID DESC

중성화 여부 파악하기

SELECT ANIMAL_ID, NAME, 
    CASE 
        WHEN SEX_UPON_INTAKE LIKE '%Neutered%' OR SEX_UPON_INTAKE LIKE '%Spayed%' THEN 'O'
        ELSE 'X'
    END AS 중성화
FROM ANIMAL_INS 
ORDER BY ANIMAL_ID

분기별 분화된 대장균의 개체 수 구하기

SELECT TO_CHAR(DIFFERENTIATION_DATE, 'Q') || 'Q' AS QUARTER,
       COUNT(*) AS ECOLI_COUNT
FROM ECOLI_DATA
GROUP BY TO_CHAR(DIFFERENTIATION_DATE, 'Q')
ORDER BY QUARTER;

혹은

SELECT CEIL(EXTRACT(MONTH FROM DIFFERENTIATION_DATE) / 3) || 'Q' AS QUARTER,
       COUNT(*) AS ECOLI_COUNT
FROM ECOLI_DATA
GROUP BY CEIL(EXTRACT(MONTH FROM DIFFERENTIATION_DATE) / 3)
ORDER BY QUARTER;

루시와 엘라 찾기

SELECT ANIMAL_ID, NAME, SEX_UPON_INTAKE
FROM ANIMAL_INS 
WHERE NAME IN ('Lucy', 'Ella', 'Pickle', 'Rogan', 'Sabrina', 'Mitty')
ORDER BY ANIMAL_ID

연도 별 평균 미세먼지 농도 조회하기

SELECT EXTRACT(YEAR FROM YM) AS YEAR, ROUND(AVG(PM_VAL1), 2) AS PM10, ROUND(AVG(PM_VAL2), 2) AS 'PM2.5'
FROM AIR_POLLUTION 
WHERE LOCATION2 = '수원'
GROUP BY EXTRACT(YEAR FROM YM)
ORDER BY YEAR

Level3

조회수가 가장 많은 중고거래 게시판의 첨부파일 조회하기

SELECT '/home/grep/src/' || F.BOARD_ID || '/' || F.FILE_ID || F.FILE_NAME || F.FILE_EXT AS FILE_PATH
FROM USED_GOODS_FILE F
INNER JOIN USED_GOODS_BOARD B ON F.BOARD_ID = B.BOARD_ID
WHERE B.VIEWS = (SELECT MAX(VIEWS) FROM USED_GOODS_BOARD)
ORDER BY F.FILE_ID DESC;
  • 조회수가 가장 많은 게시판 : WHERE B.VIEWS = (SELECT MAX(VIEWS) FROM USED_GOODS_BOARD)
  • 문자열 합치기 : ||

오랜 기간 보호한 동물(2)

SELECT O.ANIMAL_ID, O.NAME
FROM ANIMAL_OUTS O
JOIN ANIMAL_INS I ON O.ANIMAL_ID = I.ANIMAL_ID
ORDER BY O.DATETIME - I.DATETIME DESC
FETCH FIRST 2 ROWS ONLY

조건에 맞는 사용자 정보 조회하기

SELECT USER_ID,
       NICKNAME,
       CITY || ' ' || STREET_ADDRESS1 || ' ' || STREET_ADDRESS2 AS 전체주소,
       SUBSTR(TLNO, 1, 3) || '-' || SUBSTR(TLNO, 4, 4) || '-' || SUBSTR(TLNO, 8, 4) AS 전화번호
FROM USED_GOODS_USER
WHERE USER_ID IN (
    SELECT WRITER_ID
    FROM USED_GOODS_BOARD
    GROUP BY WRITER_ID
    HAVING COUNT(*) >= 3
)
ORDER BY USER_ID DESC;

조건별로 분류하여 주문상태 출력하기

SELECT ORDER_ID, PRODUCT_ID, TO_CHAR(OUT_DATE, 'yyyy-mm-dd') AS OUT_DATE, CASE
    WHEN OUT_DATE <= TO_DATE('2022-05-01', 'yyyy-mm-dd') THEN '출고완료'
    WHEN OUT_DATE IS NULL THEN '출고미정'
    ELSE '출고대기'
END AS 출고여부
FROM FOOD_ORDER 
ORDER BY ORDER_ID

대여 기록이 존재하는 자동차 리스트 구하기

SELECT DISTINCT C.CAR_ID
FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY H
JOIN CAR_RENTAL_COMPANY_CAR C ON H.CAR_ID = C.CAR_ID
WHERE C.CAR_TYPE = '세단' AND EXTRACT(MONTH FROM H.START_DATE) = 10
ORDER BY C.CAR_ID DESC
  • 중복 자동차 제거 : DISTINCT

Level4

자동차 대여 기록 별 대여 금액 구하기

WITH RENTAL_HISTORY_WITH_DURATION_TYPE AS (
    SELECT  HISTORY_ID,
            CAR_ID,
            START_DATE,
            END_DATE,
            CASE
                WHEN (END_DATE - START_DATE + 1) >= 90 THEN '90일 이상'
                WHEN (END_DATE - START_DATE + 1) >= 30 THEN '30일 이상'
                WHEN (END_DATE - START_DATE + 1) >= 7 THEN '7일 이상'
                ELSE NULL
            END AS DURATION_TYPE
    FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
)
SELECT H.HISTORY_ID AS HISTORY_ID,
       ROUND((H.END_DATE - H.START_DATE + 1) * C.DAILY_FEE * (100 - NVL(D.DISCOUNT_RATE, 0)) / 100) AS FEE
FROM RENTAL_HISTORY_WITH_DURATION_TYPE H
JOIN CAR_RENTAL_COMPANY_CAR C ON H.CAR_ID = C.CAR_ID
LEFT JOIN CAR_RENTAL_COMPANY_DISCOUNT_PLAN D ON C.CAR_TYPE = D.CAR_TYPE AND H.DURATION_TYPE = D.DURATION_TYPE
WHERE C.CAR_TYPE = '트럭'
ORDER BY FEE DESC, H.HISTORY_ID DESC
  • RENTAL_HISTORYDURATION_TYPE 컬럼 추가 : WITH 절

취소되지 않은 진료 예약 조회하기

sql
SELECT A.APNT_NO, P.PT_NAME, A.PT_NO, A.MCDP_CD, D.DR_NAME, A.APNT_YMD
FROM APPOINTMENT A
JOIN PATIENT P ON A.PT_NO = P.PT_NO
JOIN DOCTOR D ON A.MDDR_ID = D.DR_ID
WHERE TO_CHAR(A.APNT_YMD, 'YYYY-MM-DD') = '2022-04-13'
  AND A.MCDP_CD = 'CS'
  AND A.APNT_CNCL_YN = 'N'
ORDER BY A.APNT_YMD;

IS NULL


Level1

나이 정보가 없는 회원 수 구하기

SELECT COUNT(*) AS USERS
FROM USER_INFO
WHERE AGE IS NULL

Level2

NULL 처리하기

SELECT ANIMAL_TYPE, NVL(NAME, 'No name') AS NAME, SEX_UPON_INTAKE
FROM ANIMAL_INS
ORDER BY ANIMAL_ID;
  • 이름이 없는 동물의 이름은 "No name"으로 표시 : NVL(NAME, 'No name')

ROOT 아이템 구하기

SELECT I.ITEM_ID, I.ITEM_NAME
FROM ITEM_INFO I
JOIN ITEM_TREE T ON I.ITEM_ID = T.ITEM_ID
WHERE T.PARENT_ITEM_ID IS NULL
ORDER BY I.ITEM_ID

Level3

업그레이드 할 수 없는 아이템 구하기

방법 1 : 업그레이드 가능한 아이템 목록을 구한 뒤 NOT IN

SELECT ITEM_ID, ITEM_NAME, RARITY
FROM ITEM_INFO
WHERE ITEM_ID NOT IN (
    SELECT PARENT_ITEM_ID
    FROM ITEM_TREE
    WHERE PARENT_ITEM_ID IS NOT NULL
)
ORDER BY ITEM_ID DESC;

방법 2 : LEFT JOIN + NULL 체크

SELECT I.ITEM_ID, I.ITEM_NAME, I.RARITY
FROM ITEM_INFO I
LEFT JOIN ITEM_TREE T ON I.ITEM_ID = T.PARENT_ITEM_ID
WHERE T.ITEM_ID IS NULL
ORDER BY I.ITEM_ID DESC
profile
안녕하세요.

0개의 댓글