해당 글은 프로그래머스의 'SQL 고득점 Kit'을 풀고 작성한 글입니다.
https://school.programmers.co.kr/learn/challenges?tab=sql_practice_kit
< 중요! 명령어 실행 우선순위 >
1. FROM - 테이블을 가져옵니다.
2. WHERE - 조건에 맞는 행을 필터링합니다.
3. GROUP BY - 데이터를 그룹화합니다.
4. HAVING - 그룹화된 데이터에 추가 조건을 적용합니다.
5. SELECT - 최종 조회할 컬럼을 지정합니다.
6. ORDER BY - 결과를 정렬합니다.
1.평균 일일 대여 요금 구하기 (lv.1)
문제
https://school.programmers.co.kr/learn/courses/30/lessons/151136
접근
FROM -> 해당 테이블 선택
WHERE -> 특정 차종인 레코드들을 선택한 다음,
SELECT -> 평균 일일 대여 요금의 평균 구하고, 소수 첫번째 자리에서 반올림, 컬럼명 설정
풀이
SELECT ROUND(AVG(DAILY_FEE), 0) AS AVERAGE_FEE
FROM CAR_RENTAL_COMPANY_CAR
WHERE CAR_TYPE = 'SUV';
포인트
ROUND(숫자 또는 컬럼, 자릿수)
: 숫자를 반올림하는 데 사용되는 SQL 함수로, 특정 소수점 자리에서 반올림하여 결과를 반환
- 자릿수: 0이면 소수 첫 번째 자리에서 반올림. 양수면 소수점 아래 +1 자릿수에서 반올림하고, 음수면 정수 부분의 자릿수에서 반올림
2. 과일로 만든 아이스크림 고르기 (lv.1)
문제
https://school.programmers.co.kr/learn/courses/30/lessons/133025
접근
FROM -> 주어진 두개의 테이블 조인 (FLAVOR 속성이 각각 PK, FK)
WHERE -> 전체 주문량이 3000이 넘고, 주 성분이 과일인거로 튜플 제한
SELECT -> 맛 선택
ORDER BY -> 내림차순 정렬
풀이
SELECT FLAVOR
FROM ICECREAM_INFO NATURAL JOIN FIRST_HALF
WHERE TOTAL_ORDER > 3000 AND INGREDIENT_TYPE IN ('fruit_based')
ORDER BY TOTAL_ORDER DESC;
포인트
NATURAL JOIN: 속성값이 같은 컬럼끼리 JOIN되어 테이블 형성
ORDER BY: 기본값이 ASC(오름차순), 내림차순으로 정렬하려면 DESC 작성해줘야함
3. 조건에 부합하는 중고거래 댓글 조회하기 (lv.1)
문제
https://school.programmers.co.kr/learn/courses/30/lessons/164673
접근
FROM -> USED_GOODS_BOARD 와 USED_GOOD_REPLY
WHERE -> 2022년 10월에 작성된 게시판로 튜플 제한
SELECT -> 게시글 제목, 게시글 ID, 댓글 ID, 댓글 작성자 ID, 댓글 내용, 댓글 작성일 조회
풀이
SELECT BOARD.TITLE, BOARD.BOARD_ID, REPLY.REPLY_ID, REPLY.WRITER_ID, REPLY.CONTENTS, DATE_FORMAT(REPLY.CREATED_DATE, '%Y-%m-%d') AS CREATED_DATE
FROM USED_GOODS_BOARD AS BOARD JOIN USED_GOODS_REPLY AS REPLY ON BOARD.BOARD_ID = REPLY.BOARD_ID
WHERE BOARD.CREATED_DATE >= '2022-10-01' AND BOARD.CREATED_DATE < '2022-11-01'
ORDER BY REPLY.CREATED_DATE ASC, BOARD.TITLE ASC;
포인트
년도 & 월로 DATE 제한하는 부분
1. WHERE BOARD.CREATED_DATE LIKE '2022-10-%'; ( 문자열 패턴 매칭 )
2. WHERE DATE_FORMAT(BOARD.CREATED_DATE, '%Y-%m') = '2022-10'; ( 함수 변환 )
3. WHERE BOARD.CREATED_DATE >= '2022-10-01' AND BOARD.CREATED_DATE < '2022-11-01'; (
날짜 범위 조건)
문자열 패턴을 매칭하는 방법과 함수 변환 방법은 CREATED_AT 컬럼에 인덱스가 있어도 사용하지 못하는데, 날짜 범위 조건 방식을 사용하면 인덱스를 사용할 수 있어서 대용량 데이터에서 성능이 훨씬 좋다.
4. 3월에 태어난 여성 회원 목록 출력하기 (lv.2)
문제
https://school.programmers.co.kr/learn/courses/30/lessons/131120
접근
FROM -> MEMBER_PROFILE
WHERE -> DATE_OF_BIRTH가 3월 AND 여성 AND 전화번호 != NULL
SELECT -> MEMBER_ID, MEMBER_NAME, GENDER, DATE_OF_BIRTH
ORDER BY -> MEMBER_ID ASC
풀이
SELECT MEMBER_ID, MEMBER_NAME, GENDER, DATE_FORMAT(DATE_OF_BIRTH, '%Y-%m-%d') AS DATE_OF_BIRTH
FROM MEMBER_PROFILE
WHERE MONTH(DATE_OF_BIRTH) = 3 AND GENDER = 'W' AND TLNO IS NOT NULL
ORDER BY MEMBER_ID ASC
포인트
3월로만 제한: WHERE MONTH(DATE_OF_BIRTH) = 3 도 가능!!
NULL이 아닌 것 제한: IS NOT NULL
5. 서울에 위치한 식당 목록 출력하기 (lv. 4)
문제
https://school.programmers.co.kr/learn/courses/30/lessons/131118
접근
FROM -> REST_INFO와 REST_REVIEW를 REST_ID로 JOIN
WHERE -> ADDRESS 가 서울
GROUP BY -> 평균 점수를 하나의 컬럼에 넣어야 하니까, 가게 기준으로 GROUPING
SELECT -> REST_ID, REST_NAME, FOOD_TYPE, FAVORITES, ADDRESS, REVIEW_SCORE의 평균 (소수점 세번째 자리에서 ROUND)
ORDER BY -> 평균점수 기준으로 DESC, FAVORITIES DESC
풀이
SELECT REST_ID, REST_NAME, FOOD_TYPE, FAVORITES, ADDRESS, ROUND(AVG(REVIEW_SCORE), 2) AS SCORE
FROM REST_INFO NATURAL JOIN REST_REVIEW
WHERE ADDRESS LIKE '서울%'
GROUP BY REST_ID, REST_NAME, FOOD_TYPE, FAVORITES, ADDRESS
ORDER BY SCORE DESC, FAVORITES DESC;
포인트
SELECT으로 출력할 컬럼들은 GROUP BY에 명시해줘야 함!! (집계함수 제외)
GROUPING을 해줘야 그룹끼리의 평균 점수를 낼 수 있음
흐름
1. REST_INFO와 REST_REVIEW 테이블이 NATURAL JOIN되어 CARTESIAN PRODUCT 한 것에서 중복되는 컬럼 제거
2. WHERE로 서울에 있는 식당 튜플들만 컬러짐
3. GROUP BY로 같은 식당의 튜블들은 그룹화됨 (한 식당에 대한 리뷰들이 전부 묶임)
4. SELECT로 명시한 속성들 뽑아냄
5. ORDER BY에 명시된 기준들로 정렬
6. 흉부외과 또는 일반외과 의사 목록 출력하기 (lv.1)
문제
https://school.programmers.co.kr/learn/courses/30/lessons/132203
접근
SELECT -> DR_NAME, DR_ID, MCDP_CD, HIRE_YMD
FROM -> DOCTOR
WHERE -> MCDP_CD가 CS or GS
ORDER BY -> HIRE_YMD DESC, DR_NAME ASC;
풀이
SELECT DR_NAME, DR_ID, MCDP_CD, DATE_FORMAT(HIRE_YMD, '%Y-%m-%d') AS HIRE_YMD
FROM DOCTOR
WHERE MCDP_CD IN ('CS', 'GS')
ORDER BY HIRE_YMD DESC, DR_NAME ASC;
포인트
특정 컬럼의 값이 A 또는 B인 튜플을 선택 하고 싶다면, IN을 사용하기
In은 여러 값 중 하나의 일치하는 튜플들을 선택할 때 사용! 여러개 묶어서 사용 가능.
반면, '='는 특정 값 하나와 일치하는 튜플을 선택하고 싶을때 사용 가능.
최대한 In 사용하자! - 교수님왈
7. 인기있는 아이스크림 (lv.1)
문제
https://school.programmers.co.kr/learn/courses/30/lessons/133024
접근
SELECT -> FLAVOR
FROM -> FIRST_HALF
WHERE -> -
ORDER BY -> TOTAL_ORDER DESC, SHIPMENT_ID ASC
풀이
SELECT FLAVOR
FROM FIRST_HALF
ORDER BY TOTAL_ORDER DESC, SHIPMENT_ID ASC
포인트
WHERE 문 필요 없다면 쓰지 않아도 됨
8. 강원도에 위치한 생산공장 목록 출력하기 (lv.1)
문제
https://school.programmers.co.kr/learn/courses/30/lessons/131112
접근
SELECT -> FACTORY_ID, FACTORY_NAME, ADDRESS
FROM -> FOOD_FACTORY
WHERE -> ADDRESS LIKE '%강원도%'
ORDER BY -> FACTORY_ID ASC
풀이
SELECT FACTORY_ID, FACTORY_NAME, ADDRESS
FROM FOOD_FACTORY
WHERE ADDRESS LIKE '강원도%'
ORDER BY FACTORY_ID ASC
포인트
정렬의 기본값은 ASC(오름차순)이다.
9. 12세 이하인 여자 환자 목록 출력하기 (lv.1)
문제
https://school.programmers.co.kr/learn/courses/30/lessons/132201
접근
SELECT -> PT_NAME, PT_NO, GEND_CD, AGE, TLNO가 NULL이라면 'NONE'
FROM -> PATIENT
WHERE -> AGE <= 12 AND GEND_CD = 'W'
ORDER BY -> AGE DESC, PT_NAME ASC
풀이
SELECT PT_NAME, PT_NO, GEND_CD, AGE, IFNULL(TLNO, 'NONE') AS TLNO
FROM PATIENT
WHERE AGE <= 12 AND GEND_CD = 'W'
ORDER BY AGE DESC, PT_NAME ASC
포인트
속성값이 NULL이라면 다른 값으로 출력하게끔 하는건, SELECT문에서 IFNULL(속성값, 출력값)으로 설정하면 된다.
COALESCE(TLNO,'NONE') AS TLNO 도 같은 의미다.
속성값이 NULL이 아닌 다른 특정 값일때 다르게 출력하는건, 아래와 같이 CASE문을 사용하면 된다.
CASE
WHEN TLNO = '01012345678' THEN '01012345678'
ELSE TLNO
END AS TLNO
10. 조건에 맞는 도서 리스트 출력하기 (lv.1)
문제
https://school.programmers.co.kr/learn/courses/30/lessons/144853
접근
SELECT -> BOOK_ID, PUBLISHED_DATE
FROM -> BOOK
WHERE -> PUBLISHED_DATE >= 2021-01-01 AND PUBLISHED_DATE <= 2021-12-31 AND CATEGORY IN ('인문')
ORDER BY -> PUBLISHED_DATE
풀이
SELECT BOOK_ID, DATE_FORMAT(PUBLISHED_DATE, '%Y-%m-%d') AS PUBLISHED_DATE
FROM BOOK
WHERE PUBLISHED_DATE >= '2021-01-01' AND PUBLISHED_DATE < '2022-01-01' AND CATEGORY IN ('인문')
ORDER BY PUBLISHED_DATE ASC
포인트
DATE 타입이면 '' 붙여주기!
느낀점
전체적으로 많이 쉬웠는데, 빨리 어려운 문제들 많이 풀고싶당