1번
Q. 동물 보호소에 들어온 동물의 이름은 몇 개인지 조회하는 SQL 문을 작성해주세요. 이때 이름이 NULL인 경우는 집계하지 않으며 중복되는 이름은 하나로 칩니다. (링크)
count(칼럼명) -> count(distinct 칼럼명)으로 중복 제거 효과 가능
SELECT count(distinct name) 'cnt_name'
from animal_ins
where name is not null
;
2번
Q. 동물 보호소에 들어온 동물 이름 중 두 번 이상 쓰인 이름과 해당 이름이 쓰인 횟수를 조회하는 SQL문을 작성해주세요. 이때 결과는 이름이 없는 동물은 집계에서 제외하며, 결과는 이름 순으로 조회해주세요. (링크)
중복값 및 중복 개수 찾기는 group by와 having으로 가능
SELECT name,
count(name) 'cnt_name'
from animal_ins
group by name
having count(name) > 1
order by name
;
3번
Q. 동물 보호소에 가장 먼저 들어온 동물의 이름을 조회하는 SQL 문을 작성해주세요. (링크)
최고값 1개만 출력하기
mysql이라면 limit로 손쉽게 가능
select name
from animal_ins
order by datetime
limit 1
;
oracla이라면 1) rank() 함수를 사용하거나, 2) 서브쿼리를 활용함으로써 가능 (from이든 where절이든)
select name
from animal_ins
where datetime = (
select min(datetime)
from animal_ins)
;
4번
Q. ANIMAL_INS 테이블에 등록된 모든 레코드에 대해, 각 동물의 아이디와 이름, 들어온 날짜를 조회하는 SQL문을 작성해주세요. 이때 결과는 아이디 순으로 조회해야 합니다. (링크)
mysql과 oracle이 날짜 포맷 변경 함수가 다르다
지금은 mysql로 진행할 생각이니 일단 mysql의 함수들 위주로 공부하겠지만, 일단 oracla도 찾아는 두기로 했다
MySQL : date_format()
Oracle : to_date()
SELECT animal_id,
name,
date_format(datetime, '%Y-%m-%d') 'new_datetime'
from animal_ins
order by animal_id
;
5번
Q. USER_INFO 테이블에서 2021년에 가입한 회원 중 나이가 20세 이상 29세 이하인 회원이 몇 명인지 출력하는 SQL문을 작성해주세요. (링크)
처음에는 아래 주석처리한 것처럼 코드를 작성했는데,
where문제 조건을 2개 다 처리하지 않고 count() 함수에 if문을 사용했었다
위 코드는 158건, 아래는 97건을 반환한다
/*
SELECT count(if(age between 20 and 29, 1, 0)) 'users'
from user_info
where year(joined) = 2021
; # date_format(joined, '%Y')
*/
select count(*)
from user_info
where (year(joined) = 2021) and (age between 20 and 29)
;
어째서 이런 차이가 발생했는가.......
chatGPT에게 물어보고 답을 얻었는데, if(age between 20 and 29, 1, 0)가 '1' 또는 '0'을 반환하고 있으며, count() 함수는 1이든 0이든 다 세기 때문이다
즉 내가 의도한 바로 코드를 수정하면 age가 20~29에 포함되지 않을 시 count()되지 않도록 null값을 반환하도록 하면 되며,
SELECT count(if(age between 20 and 29, 1, null)) 'users'
from user_info
where year(joined) = 2021
;
그 결과는 97건으로 정답이 된다.