동명 동물 수 찾기 (SQL)

우하학·2024년 11월 9일

프로그래머스

목록 보기
6/14

진짜 다 까먹었다 진짜 클났다

동명 동물 수 찾기

동물 보호소에 들어온 동물 이름 중 두 번 이상 쓰인 이름과 해당 이름이 쓰인 횟수를 조회하는 SQL문을 작성해주세요. 이때 결과는 이름이 없는 동물은 집계에서 제외하며, 결과는 이름 순으로 조회해주세요.

  • 오류 코드
select NAME, count(*) as COUNT from ANIMAL_INS 
group by NAME having count(*)>=2
order by NAME

진짜 이거 왜 안되는 지 몰랐다... 계속 몰랐다.. 짜증 났다 근데해결함

바로 이름이 없는 동물은 집계에서 제외하기 조건을 내가 빼먹었기 때문에

group by()를 *가 아닌 NAME으로 했어야 했다.

* 과 NAME(칼럼)의 차이점

칼럼이 들어가면 NULL은 포함이 되지 않는다고 한다

  • 정답 코드
select NAME, count(*) as COUNT from ANIMAL_INS 
group by NAME having count(NAME)>=2
order by NAME

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

USER_INFO 테이블과 ONLINE_SALE 테이블에서 년, 월, 성별 별로 상품을 구매한 회원수를 집계하는 SQL문을 작성해주세요. 결과는 년, 월, 성별을 기준으로 오름차순 정렬해주세요. 이때, 성별 정보가 없는 경우 결과에서 제외해주세요.

  • 오류 코드
SELECT YEAR(SALES_DATE) as YEAR, MONTH(SALES_DATE) as MONTH, GENDER, count(distinct A.USER_ID) as USERS
FROM 
    USER_INFO A
JOIN 
    ONLINE_SALE B ON A.USER_ID = B.USER_ID
    
group by YEAR(SALES_DATE), MONTH(SALES_DATE)
order by YEAR(SALES_DATE), MONTH(SALES_DATE), GENDER

문제를 이해하지 못했던 것 같다. 결국 년, 월, 성별 별로 구매한 회원의 수를 구하는 건ㄷㅔ....

  • 정답 코드
select YEAR(SALES_DATE) as YEAR, MONTH(SALES_DATE) as MONTH, GENDER, count(distinct A.USER_ID) as USERS
from USER_INFO A
join ONLINE_SALE B on A.USER_ID = B.USER_ID
where A.GENDER is not null
group by YEAR(SALES_DATE), MONTH(SALES_DATE), A.GENDER
order by YEAR(SALES_DATE), MONTH(SALES_DATE), A.GENDER

입양 시각 구하기(2)

보호소에서는 몇 시에 입양이 가장 활발하게 일어나는지 알아보려 합니다. 0시부터 23시까지, 각 시간대별로 입양이 몇 건이나 발생했는지 조회하는 SQL문을 작성해주세요. 이때 결과는 시간대 순으로 정렬해야 합니다.

  • 오류 코드라고 하기엔 처음이라 부족한 코드
select HOUR(DATETIME) as HOURS, count(*) 
from ANIMAL_OUTS 
group by HOUR(DATETIME)
order by HOUR(DATETIME)

나의 SQL 지식으로는 이게 최선이었다. 하지만 이렇게 하면 결과는 ...

이렇게 나와서 입양된 시간이 없는 시간의 카운팅이 되지 않는 상황이다.
** 입양된 시간이 없는 시간도 카운팅이 필요함 !

  • 내가 할 수 없어서 찾아본 정답 코드
select T.hour as HOURS, ifnull(count(A.DATETIME),0)
from (
    SELECT 0 AS hour 
    UNION ALL SELECT 1 
    UNION ALL SELECT 2 
    UNION ALL SELECT 3
    UNION ALL SELECT 4 
    UNION ALL SELECT 5 
    UNION ALL SELECT 6 
    UNION ALL SELECT 7
    UNION ALL SELECT 8 
    UNION ALL SELECT 9 
    UNION ALL SELECT 10
    UNION ALL SELECT 11
    UNION ALL SELECT 12 
    UNION ALL SELECT 13 
    UNION ALL SELECT 14 
    UNION ALL SELECT 15
    UNION ALL SELECT 16 
    UNION ALL SELECT 17 
    UNION ALL SELECT 18 
    UNION ALL SELECT 19
    UNION ALL SELECT 20 
    UNION ALL SELECT 21 
    UNION ALL SELECT 22 
    UNION ALL SELECT 23
) as T
left join ANIMAL_OUTS A on T.hour = HOUR(A.DATETIME)
group by T.hour
order by T.hour

임시로 hour에 0~23시 테이블을 만들어서 그 테이블과 left join을 통해서 값이 없는 부분도 0으로 결과를 확인할 수 있게 해준다.

알아야할 것

  1. ifnull()
    -> 사용은 ifnull(count(A.DATETIME),0)으로 하였는데, 왼쪽 값이 null이면 0으로 출력하기 인 것 같다.
  2. left join
    -> left join의 예시를 보면, select * from TableA left join TableB on ~~~
    여기서 문장 그대로 TableA / TableB로 보면 left join의 주인공 테이블은 TableA가 된다. 따라서 주인공 테이블의 모든 행을 출력하게 되는 것.
    반대로 select * from TableB right join TableA on ~~~ 이라고 작성하면 위와 동일한 결과를 도출하게 된다.
    따라서 T라는 테이블의 행 (0~23) 기준으로 묶고 정렬을 하며, 카운팅을 하게 되며 값이 없다면 (null) 0으로 결과를 도출하게 된다.
  3. T 테이블에 관해서
    이걸 살펴보기 전, select 123 as temp 이 문장의 의미를 알아야 한다.
    임시 테이블을 만드는건데, 123이라는 값을 temp라는 열에 넣어 임시로 생성된 테이블이 되는 것이다.
    이걸 그대로 적용하게 되면 hour이라는 임시 열에 0이라는 값을 넣는 것이다.
    이 상태에서 UNION을 통해서 select 1~23을 해버리면 hour이라는 열에 0~23이 들어간 임시 열이 생성이 완료된다.
  4. UNION vs UNION ALL
    UNION이라는 게 합집합인데, ALL은 교집합이 들어간만큼 추가 되는 것이라 ALL이 없으면 교집합 요소가 딱 한번 들어가게 된다. 실제로 여기서는 교집합의 개수가 중요한 게 아니라 있으나 없으나 결과는 같다.

까먹지마

  1. sql에서는 =로 조건을 연산한다.
  2. count(*)은 null 포함, count(칼럼명)은 null 미포함
  3. left join, right join 문장 그대로 읽고 왼쪽 오른쪽 주인공 테이블 찾기
  4. ifnull(조건1, 조건2) 조건1이 null이라면 조건2 출력하기
  5. union은 합집합 ; all은 교집합 있는 그대로 포함하는 거
profile
코린이 탈출기

0개의 댓글