오랜만에 프로그래머스에 들어가니 문제가 추가되어 있어 포스팅합니다!
본문의 문제 순서는 제가 정리하기 편하게 관련 테이블끼리 연결한 것이므로 실제 문제 순서와 다름을 유의해주시기 바랍니다.
https://school.programmers.co.kr/learn/challenges?tab=sql_practice_kit
[테이블 설명]
- FIRST_HALF: 아이스크림 가게의 상반기 주문 정보를 담은 테이블
컬럼명 | 비고 |
SHIPMENT_ID: 아이스크림 공장에서 아이스크림 가게까지의 출하 번호 | Primary Key |
FLAVOR: 아이스크림 맛 | |
TOTAL_ORDER: 상반기 아이스크림 총 주문량 |
- ICECREAM_INFO: 아이스크림 성분에 대한 정보를 담은 테이블
컬럼명 | 비고 |
FLAVOR: 아이스크림 맛 | Primary Key |
INGREDIENT_TYPE: 아이스크림의 주 성분 |
* INGREDIENT_TYPE에서 주 성분이 설탕이면 sugar_based, 주 성분이 과일이면 fruit_based임.
[문제1] 상반기에 판매된 아이스크림의 맛을 총주문량을 기준으로 내림차순 정렬하고 총주문량이 같다면 출하 번호를 기준으로 오름차순 정렬하여 조회
SELECT FLAVOR
FROM FIRST_HALF
ORDER BY TOTAL_ORDER DESC, SHIPMENT_ID ASC;
[문제2] 상반기 아이스크림 총주문량이 3,000보다 높으면서 아이스크림의 주 성분이 과일인 아이스크림의 맛을 총주문량이 큰 순서대로 조회
SELECT I.FLAVOR
FROM FIRST_HALF F JOIN ICECREAM_INFO I
ON F.FLAVOR = I.FLAVOR
WHERE F.TOTAL_ORDER > 3000 AND I.INGREDIENT_TYPE = 'fruit_based'
ORDER BY F.TOTAL_ORDER DESC;
[테이블 설명]
- PATIENT: 종합병원에 등록된 환자정보를 담은 테이블
컬럼명 | TYPE | NULLABLE |
PT_NO: 환자번호 | VAR(10) | F |
PT_NAME: 환자이름 | VAR(10) | F |
GEND_CD: 성별코드 | VAR(1) | F |
AGE: 나이 | INT | F |
TLNO: 전화번호 | VAR(50) | T |
[문제3] 12세 이하인 여자환자의 환자이름, 환자번호, 성별코드, 나이, 전화번호를 조회하는 SQL문을 작성. 이때 전화번호가 없는 경우, 'NONE'으로 출력하고 결과는 나이를 기준으로 내림차순 정렬하고, 나이가 같다면 환자이름을 기준으로 오름차순 정렬
SELECT PT_NAME, PT_NO, GEND_CD, AGE,
CASE
WHEN TLNO IS NULL THEN 'NONE'
ELSE TLNO
END AS TLNO
FROM PATIENT
WHERE AGE <= 12 AND GEND_CD = 'W'
ORDER BY AGE DESC, PT_NAME ASC;
[테이블 설명]
- DOCTOR: 종합병원에 속한 의사 정보를 담은 테이블
컬럼명 | TYPE | NULLABLE |
DR_NAME: 의사이름 | VAR(20) | F |
DR_ID: 의사ID | VAR(10) | F |
LCNS_NO: 면허번호 | VAR(30) | F |
HIRE_YMD: 고용일자 | DATE | F |
MCDP_CD: 진료과코드 | VAR(6) | T |
TLNO: 전화번호 | VAR(50) | T |
[문제4] 진료과가 흉부외과(CS)이거나 일반외과(GS)인 의사의 이름, 의사ID, 진료과, 고용일자를 조회하는 SQL 작성. 이때 결과는 고용일자를 기준으로 내림차순 정렬하고, 고용일자가 같다면 이름을 기준으로 오름차순 정렬
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;
[테이블 설명]
- MEMBER_PROFILE: 식당 리뷰 사이트의 회원 정보를 담은 테이블
컬럼명 | TYPE | NULLABLE |
MEMBER_ID: 회원ID | VAR(100) | F |
MEMBER_NAME: 회원이름 | VAR(50) | F |
TLNO: 회원 연락처 | VAR(50) | T |
GENDER: 성별 | VAR(1) | T |
DATE_OF_BIRTH: 생년월일 | DATE | T |
[문제5] 생일이 3월인 여성 회원의 ID, 이름, 성별, 생년월일을 조회하는 SQL문을 작성. 이때 전화번호가 NULL인 경우 출력대상에서 제외하고, 결과는 회원ID를 기준으로 오름차순 정렬
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 ASC;
#WHERE절에 TO_CHAR함수 대신 EXTRACT(MONTH FROM DATE_OF_BIRTH)= '03' 사용해도 됨.
[테이블 설명]
- FOOD_FACTORY: 식품공장의 정보를 담은 테이블
컬럼명 | TYPE | NULLABLE |
FACTORY_ID: 공장ID | VAR(10) | F |
FACTORY_NAME: 공장 이름 | VAR(50) | F |
ADDRESS: 주소 | VAR(100) | F |
TLNO: 전화번호 | VAR(20) | T |
[문제6] 강원도에 위치한 식품공장의 공장 ID, 공장 이름, 주소를 조회하는 SQL 작성. 이때 결과는 공장 ID를 기준으로 오름차순 정렬
SELECT FACTORY_ID, FACTORY_NAME, ADDRESS
FROM FOOD_FACTORY
WHERE ADDRESS LIKE '강원도%'
ORDER BY FACTORY_ID;
[테이블 설명]
- USER_INFO: 의류 쇼핑몰에 가입한 회원 정보를 담은 테이블
컬럼명 | TYPE | NULLABLE |
USER_ID: 회원ID | INT | F |
GENDER: 성별 | TINYINT(1) | T |
AGE: 나이 | INT | T |
JOINED: 가입일 | DATE | F |
* GENDER 컬럼은 비어있거나 0 또는 1의 값을 가지며 0인 경우 남자, 1인 경우 여자를 나타냄
[문제7] 2021년에 가입한 회원 중 나이가 20세 이상 29세 이하인 회원이 몇 명인지 출력하는 SQL문 작성
SELECT COUNT(*)
FROM USER_INFO
WHERE TO_CHAR(JOINED, 'YYYY') = '2021' AND (AGE BETWEEN 20 AND 29);
[테이블 설명]
- ONLINE_SALE: 의류 쇼핑몰의 온라인 상품 판매 정보를 담은 테이블
컬럼명 | TYPE | NULLABLE |
ONLINE_SALE_ID: 온라인 상품 판매 ID | INT | F |
USER_ID: 회원 ID | INT | F |
PRODUCT_ID: 상품 ID | INT | F |
SALES_AMOUNT: 판매량 | INT | F |
SALES_DATE: 판매일 | DATE | F |
* 동일한 날짜, 회원 ID, 상품 ID 조합에 대해서는 하나의 판매 데이터만 존재.
[문제8] 동일한 회원이 동일한 상품을 재구매한 데이터를 구하여, 재구매한 회원 ID와 재구매한 상품 ID를 출력하는 SQL문 작성. 결과는 회원 ID를 기준으로 오름차순 정렬하고, 회원 ID가 같다면 상품 ID를 기준으로 내림차순 정렬
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;
[테이블 설명]
- ONLINE_SALE: 의류 쇼핑몰의 온라인 상품 판매 정보를 담은 테이블
컬럼명 | TYPE | NULLABLE |
ONLINE_SALE_ID: 온라인 상품 판매 ID | INT | F |
USER_ID: 회원ID | INT | F |
PRODUCT_ID: 상품ID | INT | F |
SALES_AMOUNT: 판매량 | INT | F |
SALES_DATE: 판매일 | DATE | F |
* 동일한 날짜, 회원ID, 상품ID 조합에 대해서는 하나의 판매 데이터만 존재.
- OFFLINE_SALE: 의류 쇼핑몰의 오프라인 상품 판매 정보를 담은 테이블
컬럼명 | TYPE | NULLABLE |
ONLINE_SALE_ID: 오프라인 상품 판매 ID | INT | F |
PRODUCT_ID: 상품ID | INT | F |
SALES_AMOUNT: 판매량 | INT | F |
SALES_DATE: 판매일 | DATE | F |
* 동일한 날짜, 상품ID 조합에 대해서는 하나의 판매 데이터만 존재.
[문제9] 두 테이블에서 2022년 3월의 오프라인/온라인 상품 판매 데이터의 판매 날짜, 상품ID, 유저ID, 판매량을 출력하는 SQL문 작성. OFFLINE_SALE 테이블의 판매 데이터의 USER_ID 값은NULL로 표시. 이때, 판매일을 기준으로 오름차순 정렬하고 판매일이 같다면 상품ID를 기준으로 오름차순, 상품ID까지 같다면 유저ID를 기준으로 오름차순 정렬
WITH A AS (
SELECT SALES_DATE, PRODUCT_ID, USER_ID, SALES_AMOUNT
FROM ONLINE_SALE
UNION
SELECT SALES_DATE, PRODUCT_ID, NULL USER_ID, SALES_AMOUNT
FROM OFFLINE_SALE
)
SELECT TO_CHAR(SALES_DATE,'YYYY-MM-DD') AS SALES_DATE, PRODUCT_ID, USER_ID, SALES_AMOUNT
FROM A
WHERE TO_CHAR(SALES_DATE,'YYYY-MM') = '2022-03'
ORDER BY SALES_DATE, PRODUCT_ID, USER_ID;
* 사족이지만 저는 임시테이블을 만들 때 TO_CHAR함수를 사용해서 데이터 타입을 변경하고 시작했었어요.
그래서 그런지 마지막 WHERE절에 TO_CHAR함수가 작동을 안 해서 제 머리로는 이게 정답인데 엄청 고민했었네요
저는 이럴때 SQL 실행 순서를 다시 한번 복기하고 데이터 타입을 점검하는 편입니다. 그러면 수정되는 경우가 많더라고요 ㅎ
코딩하는데 시간이 오래 걸리는 경우 다른 분들은 어떻게 했는지도 하나하나 보는 편인데
공유된 정답중에 임시테이블을 사용하는 경우는 없어서 제 코드가 비효율적인 방법인가 조금 고민스럽지만
사람이 10명이면 10개의 코드가 나오는 게 맞다는 생각으로 임하고 있습니다!!
[테이블 설명]
- REST_INFO: 식당 정보를 담은 테이블
컬럼명 | TYPE | NULLABLE |
REST_ID: 식당ID | VAR(5) | F |
REST_NAME: 식당이름 | VAR(50) | F |
FOOD_TYPE: 음식 종류 | VAR(20) | T |
VIEWS: 조회수 | NUM | T |
FAVORITES: 즐겨찾기수 | NUM | T |
PARTKING_LOT: 주차장 유무 | VAR(1) | T |
ADDRESS: 주소 | VAR(100) | T |
TEL: 전화번호 | VAR(100) | T |
- REST_REVIEW: 식당의 리뷰 정보를 담은 테이블
컬럼명 | TYPE | NULLABLE |
REVIEW_ID: 리뷰ID | VAR(10) | F |
REST_ID: 식당ID | VAR(10) | T |
MEMBER_ID: 회원ID | VAR(100) | T |
REVIEW_SCORE: 점수 | NUM | T |
REVIEW_TEXT: 리뷰 텍스트 | VAR(1000) | T |
REVIEW_DATE: 리뷰 작성일 | DATE | T |
[문제10] 서울에 위치한 식당들의 식당ID, 식당 이름, 음식 종류, 즐겨찾기수, 주소, 리뷰 평균 점수를 조회하는 SQL 작성. 이때 리뷰 평균점수는 소수점 세 번째 자리에서 반올림하고 결과는 평균점수를 기준으로 내림차순 정렬, 평균점수가 같은 경우 즐겨찾기수를 기준으로 내림차순 정렬.
SELECT A.REST_ID, A.REST_NAME, A.FOOD_TYPE, A.FAVORITES, A.ADDRESS,
ROUND(AVG(B.REVIEW_SCORE),2) AS SCORE
FROM REST_INFO A INNER JOIN REST_REVIEW B
ON A.REST_ID = B.REST_ID
WHERE A.ADDRESS LIKE '서울%'
GROUP BY A.REST_ID, A.REST_NAME, A.FOOD_TYPE, A.FAVORITES, A.ADDRESS
ORDER BY SCORE DESC, A.FAVORITES DESC;
'SQL > 프로그래머스' 카테고리의 다른 글
[프로그래머스] SQL 고득점 Kit 문제 - GROUP BY 2 (0) | 2022.12.15 |
---|---|
[프로그래머스] SQL 고득점 Kit 문제 - SUM, MAX, MIN 2 (0) | 2022.12.14 |
[프로그래머스] SQL 고득점 Kit 문제 - IS NULL (0) | 2022.09.15 |
[프로그래머스] SQL 고득점 Kit 문제 - GROUP BY (0) | 2022.09.15 |
[프로그래머스] SQL 고득점 Kit 문제 - SUM, MAX, MIN (0) | 2022.08.09 |