
소소한 성취감을 얻을 겸, SQL 문법을 복습할 겸 겸사겸사 SQLD 자격증 시험을 신청했다.
그리고 노랭이 교재와 함께 프로그래머스 SQL 코딩 테스트 문제를 병행하며, 오답 노트를 작성하고 있다.
내용 위주로 정리해봤다 🔥
- '이름'이 같은 동물 중에서는 '보호를 나중에 시작한' 동물을 먼저 보여줘야 한다.
🖍️ 정답
order by name, datetime desc;
생각을 많이 해서 오히려 헷갈렸던 문제인데, 차근차근 생각하면 쉬운 문제다.
(1) name 을 기준으로 정렬
(2) datetime 을 기준으로 desc
- 가장 먼저 들어온 이름을 조회한다.
🖍️ 정답
limit 1;
이 문제 또한 생각을 많이 했었는데, 단 하나 를 조회해야 할 경우는 limit 를 사용하면 된다.
‼️ 여기서 잠깐
일반 코딩 테스트와 달리, 프로그래머스 SQL 코딩 테스트 문제는 문법적으로 틀릴 경우, 아래와 같이 공통 에러 로그가 출력된다.
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'where name is not null' at line 7
로그 내용 중 where 이라는 내용을 통해, 어디서 에러가 시작됐는지는 알 수 있지만
위와 같은 이유들은 잘 알 수 없으므로 유심히 살펴보며 고민해봐야 한다 🔨
- '이름'이 없는 경우, 'No name' 으로 대체한다.
🖍️ 정답
select animal_type, coalesce(name, 'No name') ..
컬럼명을 대체할 수 있는 문법인 coalesce 를 사용하면 된다.
- 이름이 null 이면서 중복인 경우는 세지 않는다.
🖍️ 정답
count(distinct(name))
count 안에 distinct 를 사용하는 방식으로 적용할 수 있다.
(1) 이름이 중복인 경우
distinct 를 적용한다.(2) 세지 않는다.
count 를 사용한다.
- 두 번 이상 사용된 이름과 해당 이름이 쓰인 횟수를 조회한다.
🖍️ 정답
select name, count(name)
from animal_ins
group by name
having count(name) >= 2
order by name;
그룹화를 한 column 에 대해 조건이 들어가야 하므로, where 이 아닌 having 이 사용되어야 한다.
(1) 주체가 이름이므로 이름 에 대해 groupping 을 진행해야 한다.
group by name(2) 두 번 이상 사용된 이름과 해당 이름이 쓰인 횟수를 조회
having count(name) >= 2‼️ 여기서 잠깐
SQL 실행 순서에 따라 각 구절에 대해 scan 을 진행한다.
SELECT → FROM → JOIN → WHERE → GROUP BY → HAVING → ORDER BY
- 년/월 및 성별 별로 상품을 구매한 회원 수를 집계
🖍️ 정답
select
year(s.sales_date) as year,
month(s.sales_date) as month,
u.gender,
count(distinct u.user_id) as buyer_count
from online_sale s
join user_info u
on s.user_id = u.user_id
where u.gender is not null
group by year(s.sales_date), month(s.sales_date), u.gender
order by year(s.sales_date), month(s.sales_date), u.gender;
정말 아쉽게 틀렸던 문제였어서, 따로 오답까지 정리해보았다.
👉 이전 오답
select
year(sales_date) as year,
month(sales_date) as month,
gender > (count 는 실수로 빠진듯 하다.)
from online_sale
join user_info
on online_sale.user_id = user_info.user_id
group by year, month, gender
where gender is not null
order by year, month, gender
(1) 년/월 및 성별 별로 집계
group by 에는 별칭을 사용할 수 없다.order by 에도 별칭을 사용할 수 없다.
- 날짜를 yyy-mm-dd 형식으로 조회해야 한다.
🖍️ 정답
date_format(column, '%Y-%m-%d')
이때, %Y 형식으로 지정해야 2025과 같은 형태로 반환된다. 유의!
- 상품 카테고리 코드별 상품 개수를 출력한다.
이때, 상품 카테고리 코드는 앞 2자리씩 자르도록 한다.
또한, 상품 카테고리 코드를 기준으로 오름차순 정렬한다.
🖍️ 정답
select
substring(product_code, 1, 2) as category,
count(*)
from product
group by substring(product_code, 1, 2)
order by product_code;
문자열 기준, n자리씩 잘라야 한다면 java 에서도 사용되는 substring 을 따올리면 된다.
💡 Tip.
문제에서 ~ 별 과 같이 특정 column 을 기준으로 묶는 듯한 내용이 있거나,집계와 같은 내용이 표현되어 있다면group by+집계 함수로 바로 작성하면 된다.
- 이는 곧, group by 가 집계 함수와 같이 사용되는 사용처를 말로 풀어낸 것이기 때문이다.
substring 사용법은 다음과 같다.
substring(coulmn, start index, end index)
- 이때, zero-base 가 아닌 one-base
- end index 까지, 즉 포함이다.
- 진료과가 흉부외과(CS)이거나 외과(GS)인 경우에 대해 조회
🖍️ 정답
select
dr_name,
dr_id,
mcdp_cd,
date_format(hire_ymd, '%Y-%m-%d') as hire_ymd
from doctor
where mcdp_cd = 'CS' or 'GS'
order by hire_ymd desc, dr_name;
문자열 타입의 column 인 경우, or 연산자로 묶을 수 없다.
따라서 in 연산자를 사용해야 한다.
where column in ('condition1', 'condition2')
- 'Neutered Male' 또는 'Spayed Female' 일 경우, 'O' 그 외의 경우는 'X'
🖍️ 정답
select
animal_id,
name,
case
when sex_upon_intake = 'Neutered Male' then 'O'
when sex_upon_intake = 'Spayed Female' then 'O'
else 'X'
end
as '중성화'
from animal_ins
order by animal_id;
if 문과 같이, 특정 조건에 대해 filtering 을 진행한 다음 해당 column 을 특정 value 으로 표현하기 위해서는, case-when-then 을 사용하면 된다.
case-when-then 의 구조는 다음과 같다.
case (case; 선언)
when sex_upon_intake = 'Neutered Male' then 'O' (when; 조건, then; 조건에 따라 치환할 값)
when sex_upon_intake = 'Spayed Female' then 'O'
else 'X' (else; 그 외의 경우에 대해 치환할 값)
end