<HARD>
department top three salaries
SELECT ms.department
,ms.employee
,ms.salary
FROM(
SELECT Employee.name AS employee
,Department.name AS department
,Employee.salary
,DENSE_RANK() OVER(PARTITION BY departmentId ORDER BY salary DESC) AS rank
FROM Employee
INNER JOIN Department ON Employee.departmentId = Department.id
) ms
WHERE ms.rank <= 3;
SQL
복사
select b.name as Department
,a.name as Employee
,a.salary as Salary
from (
select *
,dense_rank() over(partition by departmentId order by salary desc) as salary_rnk
from employee
) a
inner join department b on a.departmentId = b.id
where a.salary_rnk <= 3;
SQL
복사
trips and users → 다시!!
•
cancel 된 비율 → status가 ‘cancelled_’로 시작하면서 users의 banned 가 ‘No’ 인 요청 수 / 그날 users의 banned가 ‘No’인 전체 요청 수
•
2013-10-01 날짜부터 ‘2013-10-03 날짜까지 cancel 비율 구하기(소수점 두자리 숫자까지)
select e.request_at as Day
,round(count(distinct if(e.status like 'cancelled%',e.id,null)) / count(distinct e.id),2) as "Cancellation Rate"
from (
select a.*
,b.banned
,b.role
from trips a
inner join users b on a.client_id = b.users_id
union all
select c.*
,d.banned
,d.role
from trips c
inner join users d on c.driver_id = d.users_id
) e
where e.banned = 'No'
group by e.request_at
having e.request_at between '2013-10-01' and '2013-10-03'
order by Day;
SQL
복사
select request_at as "Day"
,round(sum(case when status like 'cancelled%' then 1 else 0 end) / count(id),2) as "Cancellation Rate"
from trips
where
client_id not in (select users_id from users where role = 'client' and banned = 'Yes')
and
driver_id not in (select users_id from users where role = 'driver' and banned = 'Yes')
and
request_at between '2013-10-01' and '2013-10-03'
group by request_at;
SQL
복사
human traffic of stadium - 연속적으로 값이 나오는 행들을 출력
크게 두 유형으로 나뉜다.
→ n번 이상 연속으로 나오는 동일한 수
→ n번 이상 연속하는 수 전체
n번 이상 연속으로 나오는 동일한 수 : leetcode 180
⇒ 3,3,3,3 같이 같은 수가 n번 이상 연속해서 나옴
n번 이상 연속하는 수 전체: leetcode 601
⇒ 3,4,5,6 같이 연속한 수를 n개 이상 나옴
mysql 의 경우, 자주 사용하는 방법은 self-join , window-function 이다.
문제 : id가 연속하면서, people의 값이 ≥ 100 인 행들이 3번이상나오는 행들을 출력
→ 먼저 lead와 lag 를 최대 2번씩 한 변수들을 확인해보면 다음과 같이 나온다
WITH A AS (
SELECT id
, LEAD(id,1) OVER () n_id1
, LEAD(id,2) OVER () n_id2
, LAG(id,1) OVER () p_id1
, LAG(id,2) OVER () p_id2
, visit_date
, people
FROM stadium
WHERE people >= 100)
SQL
복사
id | n_id1 | n_id2 | p_id1 | p_id2 | people | visit_date |
2 | 3 | 5 | null | null | 109 | 2017-01-02 |
3 | 5 | 6 | 2 | null | 150 | 2017-01-03 |
5 | 6 | 7 | 3 | 2 | 145 | 2017-01-05 |
6 | 7 | 8 | 5 | 3 | 1455 | 2017-01-06 |
7 | 8 | null | 6 | 5 | 199 | 2017-01-07 |
8 | null | null | 7 | 6 | 188 | 2017-01-09 |
case when 을 이용해서 연속하는 수 정의하기
WITH A AS (
SELECT id
, LEAD(id,1) OVER () n_id1
, LEAD(id,2) OVER () n_id2
, LAG(id,1) OVER () p_id1
, LAG(id,2) OVER () p_id2
, visit_date
, people
FROM stadium
WHERE people >= 100)
SELECT id
, visit_date
, people
FROM (
SELECT CASE WHEN id + 1 = n_id1 AND id + 2 = n_id2 THEN 'Y'
WHEN id - 1 = p_id1 AND id - 2 = p_id2 THEN 'Y'
WHEN id + 1 = n_id1 AND id - 1 = p_id1 THEN 'Y'
ELSE 'N' END csc
, id
, visit_date
, people
FROM a) b
WHERE csc = 'Y'
SQL
복사
WITH a AS (SELECT id -- 기존의 연속하는 수
, people
, visit_date
, ROW_NUMBER() OVER (ORDER BY visit_date) rn -- 다른 연속하는 수 만들기
, id - ROW_NUMBER() OVER (ORDER BY visit_date) diff
FROM stadium
WHERE people >= 100)
SELECT id
, visit_date
, people
FROM a
WHERE diff IN (
SELECT diff
FROM a
GROUP BY diff
HAVING COUNT(diff) >= 3 )
SQL
복사