SQL 문제풀이 복습
문제 링크
date를 형식에 맞게 변환하는 문제.
%W : 요일 이름을 풀버전으로 반환한다. (e.g. Tuesday)
만약 소문자로 %w를 쓰게 되면 요일을 숫자 형태로 반환한다. 월요일이 1부터 시작되므로 화요일은 2로 나오는 식.
%M %e : M도 마찬가지로 월 이름을 풀버전으로 반환한다. (e.g. April)
이것도 소문자로 %m으로 쓰면 그냥 숫자 형태로 04처럼 나온다. date_format 나올 때 맨날 쓰던 %Y-%m-%d에서 보던 그것.
뒤의 %e는 날짜를 숫자 형태로 반환하는데, %d와의 차이점은 한자릿수 앞에 0이 안 붙는다는 점. 예를 들어 날짜가 9일이라고 하면 %d는 09로 반환하는데, %e는 그냥 9로 나온다. 이 문제에서는 그냥 9로 출력되어야 하므로 %e를 쓰면 됨. 참고로 %E처럼 대문자로 쓰면 뭐 없고 그냥 영문자 E가 나온다.
%Y : 년도를 4자리의 풀버전으로 반환한다. (e.g. 2024)
만약 %y처럼 소문자로 쓰게 되면 앞의 두 자리는 날아가고 24, 23, 22 이런 식으로 년도의 뒷 2자리만 나오게 된다.
SELECT DATE_FORMAT(day, "%W, %M %e, %Y") AS "day"
FROM Days;
문제 링크
말을 이해하는 게 어려운..ㅋㅋ 문제
서브쿼리를 쓰면 너무 복잡해질 것 같아서 오늘은 CTE로.
WITH result
AS (SELECT order_id,
Max(quantity) AS "max",
Avg(quantity) AS "avg"
FROM OrdersDetails
GROUP BY 1)
SELECT order_id
FROM result
WHERE max > (SELECT Max(avg)
FROM result);
문제 링크
case when을 쓸 때 조건을 2개 주는 문제.
odd_number인지 판별하려면 2로 나눴을 때 나머지가 1인지를 보면 되고,
(파이썬 문법과 동일)
이름이 M으로 시작하는 경우에 해당하면 안 되므로 not like 'M%'로 써 주면 된다.
특히 문자열 제어하는 이 부분이 자주 안 써버릇하면 헷갈리기 쉬움.
SELECT employee_id,
CASE
WHEN employee_id%2 = 1
AND name NOT LIKE 'M%' THEN salary
ELSE 0
end AS "bonus"
FROM Employees
ORDER BY 1;
SELECT YEAR(SALES_DATE) AS "YEAR",
MONTH(SALES_DATE) AS "MONTH",
GENDER,
COUNT(DISTINCT o.USER_ID) AS "USERS"
FROM ONLINE_SALE o
JOIN USER_INFO u
ON o.USER_ID = u.USER_ID
WHERE GENDER IS NOT NULL
GROUP BY 1,
2,
3
ORDER BY 1,
2,
3;
문제 링크
예시를 이상하게 주네;
SELECT CONCAT(LEFT(PRICE, 1), '0000') AS "PRICE_GROUP",
COUNT(PRODUCT_ID) AS "PRODUCTS"
FROM PRODUCT
GROUP BY 1
ORDER BY 1;
SELECT LEFT(PRODUCT_CODE, 2) AS "CATEGORY",
COUNT(*) AS "PRODUCTS"
FROM PRODUCT
GROUP BY 1
ORDER BY 1;
SELECT COUNT(*) AS "USERS"
FROM USER_INFO
WHERE age IS NULL;
문제 링크
아직도 복수정답이 인정되는 듯한 애매한 문제.
리트코드와 비교했을 때의 프로그래머스의 두드러진 약점이 이거라고 생각한다.
(물론 리트코드의 출제도 완벽한 건 아니지만!)
1트(4/7) 때의 포스팅을 보니 서브쿼리를 쓰는 게 익숙하지 않아서
공동 1등이 여러 명일 때의 쿼리를 소화하지 못했더라.
그래서 그냥 김민재의 결과만 출력하고 정답으로 인정받았던 것 같은데,
어렵게 생각할 것 없이 그냥 서브쿼리를 두 번 쓰면 된다.
지금은 자연스럽게 생각이 드는 것도 그 당시엔 그렇게 어려웠었나 보다.
제일 안쪽 서브쿼리부터 해석하면
SELECT MEMBER_NAME,
REVIEW_TEXT,
DATE_FORMAT(REVIEW_DATE, '%Y-%m-%d') AS "REVIEW_DATE"
FROM REST_REVIEW r
JOIN MEMBER_PROFILE m
ON r.MEMBER_ID = m.MEMBER_ID
WHERE r.MEMBER_ID IN (SELECT MEMBER_ID
FROM REST_REVIEW
GROUP BY 1
HAVING COUNT(*) = (SELECT COUNT(*)
FROM REST_REVIEW
GROUP BY MEMBER_ID
ORDER BY 1 DESC
LIMIT 1))
ORDER BY 3,
2;
테스트 케이스를 촘촘하게 만드는 게 생각보다 어렵겠구나 느껴지는 문제.
그와 별개로 서브쿼리를 여러 번 중첩시켜서 쓰게끔 한 건 좋다.