본문 바로가기
복기

[SQL] 프로그래머스 고득점 Kit GROUP BY

by nahowo 2025. 2. 17.

https://school.programmers.co.kr/learn/courses/30/parts/17044

GROUP BY MIN/MAX

WITH F_TYPE AS (
    SELECT FOOD_TYPE, MAX(FAVORITES) AS FAVORITES
    FROM REST_INFO
    GROUP BY FOOD_TYPE
)

SELECT A.FOOD_TYPE, A.REST_ID, A.REST_NAME, A.FAVORITES
FROM REST_INFO AS A
JOIN F_TYPE AS B
    ON A.FOOD_TYPE = B.FOOD_TYPE AND A.FAVORITES = B.FAVORITES
ORDER BY FOOD_TYPE DESC
  • 집계 함수로 MIN/MAX를 사용할 때 해당 컬럼과 관련 없는 컬럼을 SELECT하면 행이 무작위로 선정된다. 따라서 위의 예시의 경우 F_TYPE을 바로 반환하는 게 아니라 REST_INFO에서 FOOD_TYPE, FAVORITES 수를 비교해 행을 맞춘 후 출력해야 한다.

HAVING

WITH FI AS (
    SELECT ID, FISH_TYPE, IFNULL(LENGTH, 10) AS LENGTH
    FROM FISH_INFO
)

SELECT COUNT(*) AS FISH_COUNT, MAX(LENGTH) AS MAX_LENGTH, FISH_TYPE
FROM FI
GROUP BY FISH_TYPE
HAVING AVG(LENGTH) >= 33
ORDER BY FISH_TYPE
  • 집계 함수에 대한 조건을 설정할 때 HAVING을 사용할 수 있다.
  • 집계 함수와 관련된 조건이 아닐 경우는 GROUP BY 이전 WHERE에 사용한다.

BETWEEN

https://school.programmers.co.kr/learn/courses/30/lessons/151139?language=mysql

WITH CR AS (
    SELECT CAR_ID, START_DATE, COUNT(CAR_ID) AS RECORDS
    FROM CAR_RENTAL_COMPANY_RENTAL_HISTORY
    GROUP BY MONTH(START_DATE), CAR_ID
    HAVING MONTH(START_DATE) BETWEEN 8 AND 10 AND RECORDS > 0
)

SELECT MONTH(START_DATE) AS MONTH, CAR_ID, RECORDS
FROM CR
WHERE
    CAR_ID IN (SELECT CAR_ID
               FROM CR
               GROUP BY CAR_ID
               HAVING SUM(RECORDS) >= 5)
ORDER BY MONTH(START_DATE), CAR_ID DESC
  • X BETWEEN A AND B는 A ≤ X ≤ B와 동일하다.

RECURSIVE 복습

https://school.programmers.co.kr/learn/courses/30/lessons/59413?language=mysql

WITH RECURSIVE TIME AS (
    SELECT 0 AS HOUR
    
    UNION ALL
    
    SELECT HOUR + 1
    FROM TIME
    WHERE HOUR < 23
)

SELECT A.HOUR, COUNT(B.ANIMAL_ID) AS COUNT
FROM TIME AS A
LEFT JOIN 
    (SELECT ANIMAL_ID, HOUR(DATETIME) AS HOUR
     FROM ANIMAL_OUTS) AS B
    ON A.HOUR = B.HOUR
GROUP BY HOUR
ORDER BY HOUR
  • 0부터 23까지의 숫자가 테이블에 전부 존재한다는 보장이 없는 상황에서 만들어 내야 하는 문제였다. 재귀 호출을 이용해 for문처럼 사용할 수 있다. 위에서는 0부터 23까지 +1을 해줬는데 거꾸로 23부터 0까지 해도 된다.

SET

SET @HOUR = -1;
SELECT @HOUR := @HOUR + 1 AS HOUR, 
    (SELECT COUNT(*)
    FROM ANIMAL_OUTS
    WHERE @HOUR = HOUR(DATETIME)) AS COUNT
FROM ANIMAL_OUTS
WHERE @HOUR < 23
  • 위와 동일한 문제인데, 변수를 할당해서 재귀가 아닌 for문처럼 활용할 수도 있다.
  • 프로그래머스 환경에서 다른 선언문에는 ;를 사용하지 않아도 괜찮았는데 SET문에는 ;가 없으니까 오류가 났다.
  • :=는 왼쪽 피연산자에 오른쪽 피연산자를 대입하는 대입 연산자이다. 위의 예시에서는 @HOUR 변수에 @HOUR + 1 값을 대입하니까 HOUR += 1과 동일하다. 처음 SET 할당 시 = 대신 사용할 수도 있다.
  • =는 주로 비교 연산에 사용되지만 SET문에서 사용되면 대입 연산자로 사용된다.

'복기' 카테고리의 다른 글

[SQL] LEETCODE SQL 50 문제풀이  (0) 2025.03.06
[SQL] 프로그래머스 고득점 Kit SELECT  (0) 2025.02.15
[모의고사] 구현 1회차 복기  (0) 2025.02.04
[모의고사] DP 1회차 복기  (0) 2025.02.04