SQL 문제풀이 복습
문제 링크
확실하게 true인 경우만 명시해 주고
나머지(else)는 전부 false로 처리해 주면 간단하다.
괜히 operator 컬럼을 의식해서
함수에다가 넣어야지 하는 생각은 안 해도 됨.
SELECT left_operand,
operator,
right_operand,
CASE
WHEN operator = '<'
AND v1.value < v2.value THEN 'true'
WHEN operator = '>'
AND v1.value > v2.value THEN 'true'
WHEN operator = '='
AND v1.value = v2.value THEN 'true'
ELSE 'false'
end AS "value"
FROM Expressions e
JOIN Variables v1
ON e.left_operand = v1.name
JOIN Variables v2
ON e.right_operand = v2.name;
문제 링크
1트(7/16)에서는 괜히 apple 따로, orange 따로 판매량을 계산했네..ㅎㅎ
집계함수와 case when을 조합하면 그럴 필요 없이 깔끔하게 뽑을 수 있다.
SELECT sale_date,
Sum(CASE
WHEN fruit = 'apples' THEN sold_num
end) - Sum(CASE
WHEN fruit = 'oranges' THEN sold_num
end) AS "diff"
FROM Sales
GROUP BY 1;
문제 링크
1트(7/18) 때처럼 CTE를 안 쓰고
서브쿼리만으로 해결한 버전.
하루에 여러 번 로그인하는 경우도 있을 수 있으므로,
group by를 해서 (인라인뷰 a) 하루의 로그인을 고유하게 묶어준 다음
date_sub과 window 함수를 이용해 group_id를 구했다. (인라인뷰 b)
이 문제의 킥은 이 group_id를 구하는 과정.
그리고 마지막은 id와 group_id를 기준으로 다시 그루핑해서
count(*)가 5 이상인 경우, 즉 연속해서 5일 이상 로그인한 id만 뽑은 후
Accounts 테이블과 join해서 name을 불러오면 된다.
SELECT DISTINCT b.id,
a.name
FROM (
SELECT id,
date_sub(login_date, INTERVAL Rank() over(partition BY id ORDER BY login_date) day) AS "group_id"
FROM (
SELECT id,
login_date
FROM Logins
GROUP BY 1,
2) a) b
JOIN Accounts a
ON b.id = a.id
GROUP BY id,
group_id
HAVING count(*) >= 5
ORDER BY 1 ASC;