[Lv3] 프로그래머스 MySQL 문제모음

17904 단어 algorithmalgorithm

오랜기간 보호한 동물(1)

나의 풀이

ANIMAL_INSANIMAL_OUTSLEFT JOIN시켜 NULL값을 가진 행만 찾아낸다.

SELECT A.NAME, A.DATETIME
    FROM ANIMAL_INS A 
    LEFT JOIN ANIMAL_OUTS B
        ON A.ANIMAL_ID = B.ANIMAL_ID
WHERE B.ANIMAL_ID IS NULL
ORDER BY A.DATETIME
LIMIT 3
;

오랜기간 보호한 동물(2)

나의 풀이

가장 보호기간이 길다는 것은 나간날짜-들어온날짜가 가장 크다는 것을 의미한다.

SELECT INS.ANIMAL_ID, INS.NAME
    FROM ANIMAL_INS INS
    JOIN ANIMAL_OUTS OUTS
        ON INS.ANIMAL_ID = OUTS.ANIMAL_ID
ORDER BY (OUTS.DATETIME-INS.DATETIME) DESC
LIMIT 2
;

보호소에서 중성화한 동물

나의 풀이

SELECT A.ANIMAL_ID, A.ANIMAL_TYPE, A.NAME 
    FROM ANIMAL_INS A
    JOIN ANIMAL_OUTS B
        ON A.ANIMAL_ID = B.ANIMAL_ID
WHERE A.SEX_UPON_INTAKE LIKE 'Intact%' AND (B.SEX_UPON_OUTCOME LIKE 'Spayed%' OR B.SEX_UPON_OUTCOME LIKE 'Neutered%')
ORDER BY A.ANIMAL_ID;

다른 분의 풀이

WHERE 조건을 A와 B의 중성화 데이터가 다른 것으로 주어, 중성화된 동물 데이터를 찾아내었다. 두 테이블의 값이 다르다는 것은, 들어올때는 중성화가 되어있지 않았지만 나갈때에는 중성화가 되었다는 것을 의미한다. (이미 중성화가 된 채로 들어왔다면 나갈때에도 중성화가 되어있으므로 변하지 않음)

SELECT A.ANIMAL_ID, A.ANIMAL_TYPE, A.NAME 
    FROM ANIMAL_INS A
    JOIN ANIMAL_OUTS B
        ON A.ANIMAL_ID = B.ANIMAL_ID
WHERE A.SEX_UPON_INTAKE != B.SEX_UPON_OUTCOME
ORDER BY A.ANIMAL_ID;

있었는데요 없었습니다

나의 풀이

보호 시작일(ANIMAL_INS.DATETIME)보다 입양일(ANIMAL_OUTS.DATETIME)이 더 빠른(더 오래된) 동물의 데이터를 조회해야한다.

어떤 날짜를 크기비교하면, 1970년 1월 1일부터 해당 날짜까지의 차를 밀리세컨드로 구한 값을 비교한다. 따라서 ANIMAL_INS.DATETIME>ANIMAL_OUTS.DATETIMEANIMAL_INS.DATETIME이 더 최근 날짜이므로, getTime을 했을때 더 값이 크다는 것을 의미한다.

SELECT A.ANIMAL_ID, A.NAME 
    FROM ANIMAL_INS A
    JOIN ANIMAL_OUTS B
        ON A.ANIMAL_ID = B.ANIMAL_ID
WHERE A.DATETIME>B.DATETIME
ORDER BY A.DATETIME
;

없어진 기록 찾기

나의 풀이

Left Join과 Right Join은 기능이 동일하므로, 테이블 작성 순서만 변경해주면 된다.
A LEFT JOIN B === B RIGHT JOIN A

//Left Join
SELECT OUTS.ANIMAL_ID, OUTS.NAME 
    FROM ANIMAL_OUTS OUTS
    LEFT JOIN ANIMAL_INS INS
        ON OUTS.ANIMAL_ID = INS.ANIMAL_ID
WHERE INS.ANIMAL_ID IS NULL
ORDER BY OUTS.ANIMAL_ID;

//Right Join
SELECT OUTS.ANIMAL_ID, OUTS.NAME 
    FROM ANIMAL_INS INS
    RIGHT JOIN ANIMAL_OUTS OUTS
        ON OUTS.ANIMAL_ID = INS.ANIMAL_ID
WHERE INS.ANIMAL_ID IS NULL
ORDER BY OUTS.ANIMAL_ID;

헤비 유저가 소유한 장소

다른 분의 풀이 (1)

  • 2회이상 조회된 HOST_ID 목록을 서브 쿼리 테이블로 만든다.
  • WHERE문에서 IN을 사용하여 서브쿼리 테이블에 존재하는 HOST_ID를 찾아 이에 해당하는 행만 조회한다.
SELECT *
	FROM PLACES
WHERE HOST_ID IN (
  SELECT HOST_ID 
  	FROM PLACES
  	GROUP BY HOST_ID
  	HAVING COUNT(HOST_ID) > 1
)
ORDER BY ID
;

다른 분의 풀이 (2)

  • EXISTS는 괄호 안의 서브쿼리는 값이 있다면 true를 리턴하고, 없다면 false를 리턴한다.
  • IN은 데이터 셋을 생성하고, 매번 데이터를 확인해야하기 때문에 성능이 떨어지는 반면, EXISTS는 해당값이 존재하는지가 true, false로 바로 확인할 수 있으므로 IN보다 성능이 좋다.
  • IN 보다는 EXISTS를 쓰는 것이 적절하다.
SELECT * FROM PLACES P1
WHERE EXISTS (
  SELECT 1 FROM PLACES P2
  WHERE P1.HOST_ID = P2.HOST_ID
  GROUP BY HOST_ID
  HAVING COUNT(ID) > 1
)
ORDER BY ID
;

EXISTS와 IN 비교

  • EXISTS

    • EXISTS 뒤의 괄호 안에는 서브쿼리만 들어갈 수 있다.
    • 처리순서: 메인쿼리 -> 서브쿼리 (순서대로)
      서브쿼리에서 메인쿼리의 정보를 가져올 수 있으므로 서브에서 메인의 정보를 가져와 조건을 설정할 수 있다.
    • 서브쿼리에 대한 결과가 존재하는지만 확인한다.
    • NULL 값에 대해 TRUE를 리턴한다.
  • IN

    • IN 뒤에 특정 값이나 서브쿼리가 들어갈 수 있다.
    • 처리순서: 서브쿼리 -> 메인쿼리 (서브먼저)
      따라서 서브쿼리에서 메인쿼리의 정보를 가져올 수 없다.
    • NULL 값에 대해 FALSE를 리턴한다.
      WHERE name IN (null, 'hello')인 경우를 풀어쓰면 다음과 같다. WHERE name = null OR name = 'hello' null값은 IS NULL로 비교되어야하는데 등호로 비교되고 있으므로 false가 나오게 되어 name='hello'인 것들로만 필터링된다. NOT IN의 경우도 마찬가지이다. WHERE name NOT IN (null, 'hello')를 풀어쓰면 WHERE name != null AND name !='hello'이다. null값은 IS NOT NULL로 비교되어야하므로 false를 반환하여 empty row를 반환한다.

좋은 웹페이지 즐겨찾기