[프로그래머스] SQL문제 다 풀기 2트

klean·2021년 5월 6일
0

SELECT(쉬워서 안 봐도 될 듯)

1. 모든 레코드 조회하기(정답)

SELECT *
FROM ANIMAL_INS
ORDER BY ANIMAL_ID;

2. 역순 정렬하기(정답)

SELECT name, datetime
from animal_ins
order by animal_id desc

3. 아픈 동물 찾기(정답)

SELECT animal_id, name
from animal_ins
where intake_condition LIKE "SICK"
order by animal_id;

4. 어린 동물 찾기(정답)

select animal_id, name
from animal_ins
where INTAKE_CONDITION NOT LIKE "AGED"
order by animal_id;

5. 동물의 아이디와 이름(정답)

select animal_id, name
from animal_ins
order by animal_id;

6. 여러 기준으로 정렬하기(정답)

SELECT animal_id, name, datetime
from animal_ins
order by name asc, datetime desc;

7. 상위 n개 레코드(정답)

최고참 1마리의 이름을 출력

SELECT name
from animal_ins
order by datetime asc
limit 1;

SUM, MAX, MIN

  • count(*) -> null 포함해서 다 센다
  • count(표현식|칼럼 이름) -> null

1. 최대값 구하기(오답)

SELECT MAX(DATETIME)
FROM ANIMAL_INS

3. 동물 수 구하기(안품)

SELECT count(ANIMAL_ID)
FROM ANIMAL_INS

4. 중복제거하기(정답)

#답1
SELECT count(distinct(name))
from animal_ins

#답2
SELECT count(distinct(name))
from animal_ins
where name is not null

STRING, DATE

like의 경우 대소문자를 구별하지 않는다.

1. 루시와 엘라 찾기(정답)

SELECT ANIMAL_ID, NAME, SEX_UPON_INTAKE
FROM ANIMAL_INS
WHERE NAME LIKE 'LUCY' OR
NAME LIKE 'ELLA' OR
NAME LIKE 'PICKLE' OR
NAME LIKE 'ROGAN' OR
NAME LIKE 'SABRINA' OR
NAME LIKE 'MITTY'
ORDER BY ANIMAL_ID;

2. EL이 들어가는 동물 찾기(정답)

3. 중성화 여부 파악하기(정답)

SELECT ANIMAL_ID, NAME, IF(SEX_UPON_INTAKE LIKE "%NEUTERED%" OR
                          SEX_UPON_INTAKE LIKE "%SPAYED%", 'O','X') as SEX_MOD
                          
FROM ANIMAL_INS
ORDER BY ANIMAL_ID;

4. 오랜 기간 보호한 동물(오답)

SELECT ANIMAL_ID, AI.NAME # ANIMAL_ID는 USING 조건이라 어느 태이블건지 상관X
FROM ANIMAL_INS AS AI JOIN ANIMAL_OUTS AS AO USING(ANIMAL_ID)
ORDER BY AO.DATETIME - AI.DATETIME DESC
LIMIT 2;

테이블 이름을 rename을 한 경우 rename테이블이름.필드 이렇게 쓰는 것이 옳다.
단 using() 에 들어가 있는 필드의 경우 꼭 그럴 필요는 없다.
DESC를 빼먹었다.

내가 한 게 문제 조건에 잘 맞는지 SELECT *로 뽑아봐야겠다...

5. DATETIME에서 DATE로 형변환(오답)

SELECT ANIMAL_ID, NAME, DATE_FORMAT(DATETIME,"%Y-%m-%d") AS 날짜
FROM ANIMAL_INS
ORDER BY ANIMAL_ID;

정말.. 어이없게 틀렸다.. 2018 이런식으로 4자리 하려면 %y가 아니고 %Y야..

IS NULL

1. 이름이 없는 동물의 아이디(정답)

SELECT ANIMAL_ID
FROM ANIMAL_INS
WHERE NAME IS NULL
ORDER BY ANIMAL_ID;

2. 이름이 있는 동물의 아이디(정답)

SELECT ANIMAL_ID
FROM ANIMAL_INS
WHERE NAME IS NOT NULL
ORDER BY ANIMAL_ID;

3. NULL 처리하기(정답)

이름이 NULL인 동물은 이름란을 "NO NAME" 으로 표기하라

SELECT ANIMAL_TYPE, IF(NAME IS NULL, "No name", NAME) AS NAME_MOD,
SEX_UPON_INTAKE
FROM ANIMAL_INS
ORDER BY ANIMAL_ID;

JOIN

1. 없어진 기록찾기(정답)

천재지변으로 인해 일부 데이터가 유실되었습니다. 입양을 간 기록은 있는데, 보호소에 들어온 기록이 없는 동물의 ID와 이름을 ID 순으로 조회하는 SQL문을 작성해주세요.

SELECT ANIMAL_ID, NAME
FROM ANIMAL_OUTS
WHERE ANIMAL_ID NOT IN
(SELECT ANIMAL_ID
FROM ANIMAL_INS) #RENAME 하면 어케 되는지 보기
ORDER BY ANIMAL_ID

rename을 했을 때 에러가 났다... where 절에 있는 derived relation은 rename을 안하나보다..
cf) 동물원에서 같은 이름을 가진 동물들의 수를 (이름, 중복이름 수)로 뽑아내라
조건1) 이름에 대해 오름차순 정렬
조건2) NULL은 무시(세지 않음)

SELECT NAME, NAME_CNT
FROM(
    SELECT NAME, count(NAME) AS NAME_CNT
    FROM ANIMAL_INS
    GROUP BY NAME
    ) AS T #여기!!
WHERE NAME_CNT>1
ORDER BY NAME #여기!!

2. 있었는데요 없었습니다(정답)

SELECT ANIMAL_ID, AI.NAME
FROM ANIMAL_INS AS AI JOIN ANIMAL_OUTS AS AO USING(ANIMAL_ID)
WHERE AI.DATETIME > AO.DATETIME
ORDER BY AI.DATETIME ASC;

3. 오랜기간 보호한 동물(1)(정답)

SELECT NAME, DATETIME
FROM ANIMAL_INS
WHERE ANIMAL_ID NOT IN
(SELECT ANIMAL_ID
FROM ANIMAL_OUTS)
ORDER BY DATETIME
LIMIT 3

4. 보건소에서 중성화한 동물(정답)

SELECT ANIMAL_ID, AI.ANIMAL_TYPE, AI.NAME
FROM ANIMAL_INS AS AI JOIN ANIMAL_OUTS AS AO USING(ANIMAL_ID)
WHERE (SEX_UPON_INTAKE NOT LIKE "%NEUTERED%" AND
       SEX_UPON_INTAKE NOT LIKE "%SPAYED%") AND
       (SEX_UPON_OUTCOME LIKE "%NEUTERED%" OR
       SEX_UPON_OUTCOME LIKE "%SPAYED%")
ORDER BY ANIMAL_ID

GROUP BY

SELECT [DISTINCT] 칼럼명 [ALIAS명]
FROM 테이블명
[WHERE 조건식 ][GROUP BY 칼럼(Column)이나 표현식]
[HAVING 그룹조건식];

  • GROUP BY 절에서는 SELECT 절과는 달리 ALIAS 명을 사용불가
  • 집계 함수는 WHERE 절에는 올 수 없다. (집계 함수를 사용할 수 있는 GROUP BY 절보다 WHERE 절이 먼저 수행)
  • WHERE 절은 전체 데이터를 GROUP으로 나누기 전에 행들을 미리 제거시킨다.
  • HAVING 절은 GROUP BY 절의 기준 항목이나 소그룹의 집계 함수를 이용한 조건을 표시할 수 있다.
  • GROUP BY 절에 의한 소그룹별로 만들어진 집계 데이터 중, HAVING 절에서 제한 조건을 두어 조건을 만족하는 내용만 출력한다.
  • HAVING 절은 일반적으로 GROUP BY 절 뒤에 위치한다.

1. 고양이와 개는 몇 마리 있을까

SELECT ANIMAL_TYPE, COUNT(ANIMAL_ID)
FROM ANIMAL_INS
WHERE ANIMAL_TYPE LIKE "CAT" OR ANIMAL_TYPE LIKE "DOG"
GROUP BY ANIMAL_TYPE
ORDER BY ANIMAL_TYPE

2. 동명 동물 수 찾기(오답)

# 답1
SELECT name, count(animal_id)
from animal_ins
where name is not null
group by name
having count(animal_id)>=2
order by name;

#답2
SELECT NAME, COUNT(NAME)
FROM ANIMAL_INS
GROUP BY NAME
HAVING COUNT(NAME)>1
ORDER BY NAME ASC
#여기서 HAVING COUNT(*)>1 혹은 COUNT(ANIMAL_ID)>1를 사용할 수 있다고 실수 할 수 있는데 그러면 NULL을 세게 된다

#답3
SELECT NAME, NAME_CNT
FROM(
    SELECT NAME, count(NAME) AS NAME_CNT
    FROM ANIMAL_INS
    GROUP BY NAME
    ) AS T #여기!!
WHERE NAME_CNT>1
ORDER BY NAME #여기!!

3. 입양 시각 구하기(1) (정답)

# 답1.
SELECT hour(datetime), count(hour(datetime))
from animal_outs
where hour(datetime)>=9 and hour(datetime)<20
group by hour(datetime)
order by hour(datetime)
# 답2
SELECT hour(datetime), count(animal_id) #datetime이 notnull이라 datetime이 null인 걸 세지 않음
from animal_outs
where hour(datetime)>=9 and hour(datetime)<20
group by hour(datetime)
order by hour(datetime)

4. 입양 시각 구하기(2) (오답)

0시부터 23시까지의 입양횟수를 뽑아내야함. 근데 0시같은 때엔 입양 레코드가 존재하지 않음

SET @hour := -1; -- 변수 선언

SELECT (@hour := @hour + 1) as HOUR,
(SELECT COUNT(*) FROM ANIMAL_OUTS WHERE HOUR(DATETIME) = @hour) as COUNT
FROM ANIMAL_OUTS
WHERE @hour < 23

#답2
set @h:=-1;
SELECT (@h := @h+1) as h, 
(select count(hour(datetime)) from animal_outs where hour(datetime) = @h) as cnt
from animal_outs
where @h<23
#답3
-- 코드를 입력하세요
set @h:=-1;
SELECT (@h := @h+1) as h, 
(select count(hour(datetime)) from animal_outs where hour(datetime) = @h) as cnt
from animal_outs
where @h<23
order by h #여기

summer/winter coding 2019

우유와 요거트가 담긴 장바구니(정답)

SELECT distinct(cart_id)
from cart_products as a join cart_products as b using(cart_id)
where a.name like "milk" and b.name like "yogurt"
order by cart_id;

distint와 order by에 유의
where 절에 a가 우유, b가 요거트인 거 고르기만 하면 되는 이유 : 같은 테이블을 조인했기 때문에 a가 우유, b가 요거트인 join 결과물이 있으면, a가 요거트, b가 우유인 join 결과물도 있다는 거기 때문이다.

2021 Dev-matching : 웹 백엔드

헤비 유저가 소유한 장소(반오답)

정말 어렵게 푼 문제

SELECT ID, NAME, HOST_ID
FROM PLACES
WHERE HOST_ID IN
    (SELECT DISTINCT(HOST_ID)
    FROM (SELECT DISTINCT(HOST_ID), COUNT(HOST_ID) FROM PLACES GROUP BY HOST_ID HAVING COUNT(HOST_ID)>=2) AS T
     )
ORDER BY ID

장소를 2개 등록 한 유저를 헤비유저라고 한다.
먼저 헤비유저를 골라낸 뒤 in operand를 사용해서 헤비유저가 등록한 장소들을 뽑아냈는는데...
이러다보니 select가 3개 겹쳐져버렸다.. 이거때문에 rename해주는 데서 실수할거같아..

모범답안

group by의 대상인 aggregate function 이 select에 없고 having 절에 있는 독특한 쿼리였다..

SELECT *
FROM PLACES
WHERE HOST_ID IN (
    SELECT HOST_ID FROM PLACES
    GROUP BY HOST_ID HAVING COUNT(ID)>1)
ORDER BY ID

0개의 댓글