-
12/15스파르타/TIL(Today I Learned) 2023. 12. 15. 15:04
1164. Product Price at a Given Date
select distinct product_id, 10 as price #변경 전 모든 제품의 가격은 10을 나타냄. from Products where product_id not in (select distinct product_id from Products where change_date <='2019-08-16' ) # 서브쿼리의 결과는 CHANGE_DATE가 8월16일 이전인 ID를 추출한다. # 8월 16일 이후에 변경된 상품 = 16일 이전에는 변경 전이다 = 가격 10이다. union select product_id, new_price as price from Products where (product_id,change_date) in (select product_id , max(change_date) as date from Products where change_date <='2019-08-16' group by product_id) #가장 최근 변경된 날짜 중8월16일이 넘지 않는 ID와 DATE를 조건을 건다.
2019-08-16에 모든 제품의 가격을 알아볼 수 있는 솔루션을 작성하세요.
모든 제품의 가격이 변경되기 전에 10이라고 가정하세요.문제를 보면 일단 16일에 변경 된 가격은 NEW_PRICE = PRICE가 된다.
16일 이전의 변경된 가격 중 가장 최근에 변경된 가격이 PRICE가 된다.
16일 이후에 변경된 가격은 문제에서 주어진 가격이 변경되기 전에 해당이 되기 때문에
10으로 PRICE가 고정이 된다.
1204. Last Person to Fit in the Bus
버스를 타기 위해 기다리는 사람들이 줄을 서 있다.
하지만 버스는 무게 제한이 1000kg이라 탑승하지 못하는 분들도 있을 수 있습니다
. 체중 제한을 초과하지 않고 버스에 탈 수 있는 마지막 사람의 personon_name을 찾는 해를 작성한다.
테스트 케이스들은 제 1 사람이 체중 제한을 초과하지 않도록 생성된다예시를 보면 누적합을 통해서 구하면 쉬울 것 같아서 서브쿼리안에 누적합을 넣었다.
누적합을 구하고 FROM절에 서브쿼리를 넣어 WHERE로 누적합의 조건을 1000이하로
설정하였다.
누적합은 TURN을 기준으로 오름차순 정렬을 했다.
SELECT PERSON_NAME FROM ( SELECT TURN,PERSON_NAME,SUM(WEIGHT) OVER(ORDER BY TURN) AS TOTAL_WEIGHT FROM QUEUE ) A WHERE TOTAL_WEIGHT <= 1000
여기까지는 코드를 매우 수월하게 진행했지만 이 다음 MAX(TURN)값을 구하고 싶은데
WHERE절에는 MAX가 들어갈 수 없었다.
GROUP BY로 묶어보기도 하고 여러가지 시도를 했지만 실패했다.
해답을 보니 나와 같은 WINDOW함수를 사용한 사람의 답안이 있었다.
그 사람은 MAX(TURN)을 사용하는 것이 아니라 ORDER BY TURN DESC를 사용해서
TURN을 내림차순 정렬하여 MAX(TURN)과 같은 효과를 냈고
LIMIT 1을 사용하여 1개만 추출했다.
이를 통해 ORDER BY 와 LIMIT를 통해 MAX를 만들어 낼 수 있구나를 또 배웠다.
# 정답 코드 SELECT PERSON_NAME FROM ( SELECT TURN,PERSON_NAME,SUM(WEIGHT) OVER(ORDER BY TURN) AS TOTAL_WEIGHT FROM QUEUE ) A WHERE TOTAL_WEIGHT <= 1000 ORDER BY TURN DESC LIMIT 1
문제를 보면 income에 따라서 구간을 나누는 문제이다
처음에 case when으로 각 income별로 나눈다음
count를 하면 문제가 쉽게 풀리겠구나 싶었다.
SELECT CATEGORY ,COUNT(CATEGORY) accounts_count FROM ( SELECT CASE WHEN INCOME < 20000 THEN "Low Salary" WHEN INCOME BETWEEN 20000 AND 50000 THEN "Average Salary" WHEN INCOME > 50000 THEN "High Salary" END AS category FROM ACCOUNTS ) A GROUP BY 1
결과를 보면 group by로 묶어서 category별로 잘 나타낸듯 싶지만 마지막 average_salary를 만족하지 못했다.
결과에서는 모든 category를 다 보여주면서 count를 하는 문제이다
그럼 어찌 해야하는가?
각 행을 따로따로 하나씩 만드는 것이다. 이 말은 category를 나눠버린다는 뜻이다
SELECT "Low Salary" AS category, sum(income < 20000) AS accounts_count FROM Accounts UNION SELECT "Average Salary" AS category, sum(income BETWEEN 20000 AND 50000) AS accounts_count FROM Accounts UNION SELECT "High Salary" AS category, sum(income > 50000) AS accounts_count FROM Accounts order by 2 desc
코드를 보면 income <20000 아래인 행을 다 더한다 = count를 하는 것과 동일하다
union으로 중복을 제거해서 합치는 것이다.
이렇게 하면 모든 category가 출력이 된다.
하나 하나 만드는 과정이였다. 물론 나는 이렇게 생각 못했다..ㅎ