2021-02-28

185.部门工资前三高的所有员工

# method 1
select Department, Employee, Salary from 
(select d.name as Department, e.Name as Employee, e.Salary,
dense_rank() over(partition by DepartmentId order by Salary desc) as 'rank' 
from Employee e 
inner join Department d 
on e.DepartmentId = d.Id) sub 
where sub.rank <= 3

# method 2
select d.Name as Department, e1.Name as Employee, e1.salary 
from Department d, Employee e1, Employee e2
where d.Id = e1.DepartmentId and e1.DepartmentId = e2.DepartmentId and e1.Salary <=e2.Salary 
group by e1.name
having count(distinct e2.Salary) <= 3
order by d.Name, e1.Salary desc, e1.Name

# method 3
select
    d.Name as 'Department', e1.name as 'Employee', e1.Salary
from 
    Employee e1 
    join Department d on e1.DepartmentId = d.Id 
where 3 > (
    select count(distinct e2.Salary) from Employee e2 
    where e2.Salary > e1.Salary and e1.DepartmentId = e2.DepartmentId
)

262.行程和用户

# method 1
select request_at as 'Day',
    round(sum(if(Status!='completed',1,0))/count(*),2) as 'Cancellation Rate'
from Trips t 
 join Users u1 on t.Client_Id = u1.Users_Id and u1.Banned = 'No'
 join Users u2 on t.Driver_Id = u2.Users_Id and u2.Banned = 'No'
 WHERE	
    request_at BETWEEN '2013-10-01' AND '2013-10-03'
group by request_at

# method 2
# Write your MySQL query statement below 
select  Request_at as Day, 
    round(sum(if(Status!='completed',1,0))/count(*),2) as 'Cancellation Rate'
from 
(select *
from Trips 
where Client_Id  not in (select Users_Id from Users where Banned = 'Yes')  
    and Driver_Id not in (select Users_Id from Users where Banned = 'Yes') 
    and Request_at between '2013-10-01' and '2013-10-03'
) sub 
group by Request_at

569.员工薪水中位数

# method 1
SELECT Id, Company, Salary
FROM Employee
WHERE Id in
(select e1.Id 
from Employee e1, Employee e2 
where e1.Company = e2.Company
group by e1.Id
having sum(case when e1.Salary <= e2.Salary then 1 else 0 end) >= count(*)/2
and sum(case when e1.Salary >= e2.Salary then 1 else 0 end) >= count(*)/2)
GROUP BY Company, Salary
ORDER BY Company

# method 2
select Id, Company, Salary
from 
(select *, row_number() over(partition by Company order by Salary) as ranking,
count(*) over(partition by Company) as num
from Employee) sub 
where ranking >= num/2 and ranking <= num/2+1

571.给定数字的频率查询中位数

百度百科:一个数集中最多有一半的数值小于中位数,也最多有一半的数值大于中位数。
# method 1
select avg(Number) as median 
from(
    select Number,
    sum(Frequency) over(order by Number) as asc_num,
    sum(Frequency) over(order by Number desc) as desc_num
    from Numbers 
) t1, (select sum(Frequency)/2 as total from Numbers) t2
where t1.asc_num >= t2.total and t1.desc_num >= t2.total

# method 2
select avg(sub.Number) as median 
from 
(select 
    n1.Number,
    sum(if(n2.Number < n1.Number, n2.Frequency, 0)) as count_small,
    sum(if(n2.Number > n1.Number, n2.Frequency, 0)) as count_big,
    s.total 
from Numbers n1, Numbers n2, (select sum(Frequency) total FROM Numbers) s
group by n1.Number
having count_small<= floor(s.total/2 ) and count_big <= floor(s.total/2 )) sub 

579.查询员工的累计薪水

# method 1  两表连接
select a.Id, a.Month, sum(b.Salary) as Salary
from Employee a 
join Employee b 
on a.Id = b.Id and a.Month >= b.Month and b.Month >= a.Month-2
where (a.Id, a.Month) not in (select Id, Max(Month) from Employee group by Id)
group by a.Id, a.Month
order by a.Id, a.Month desc

# method 2 三表连接
select 
    a.Id, 
    a.Month, 
    (ifnull(a.Salary, 0) + ifnull(b.Salary, 0) + ifnull(c.Salary, 0)) as Salary
from Employee a
left join Employee b on a.Id = b.Id and a.Month = b.Month + 1
left join Employee c on a.Id = c.Id and a.Month = c.Month + 2 
where (a.Id, a.Month) not in (select Id, max(Month) from Employee group by Id)
group by a.Id, a.Month  
order by a.Id, a.Month desc 


# method 3
select Id, Month, Salary 
from 
(select Id, Month, 
    sum(Salary) over(partition by Id order by Month rows between 2 preceding and current row) as Salary, 
    lead(Month,1,0) over(partition by Id order by Month) lm
from Employee) sub 
where lm != 0 
order by Id, Month desc

601.体育馆的人流量

# method 1
with sub as(
    select 
        id, visit_date, people,
        id - rank() over(order by id) rk 
    from Stadium 
    where people >= 100
)
select 
    id, visit_date, people 
from sub  
where rk in 
(select rk from sub group by rk having count(*)>=3)

# method 2 lead lag函数!!
select 
    id, visit_date, people
from 
(select 
    id, visit_date,
    lag(people, 2)  over(order by id) as lg2,
    lag(people, 1)  over(order by id) as lg,
    people,
    lead(people, 1)  over(order by id) as ld1,
    lead(people, 2)  over(order by id) as ld2
from Stadium) sub 
where (sub.lg2 >= 100 and sub.lg >= 100 and sub.people >= 100)
or (sub.lg>=100 and sub.people>=100 and sub.ld1 >= 100)
or(sub.people>=100 and sub.ld1>=100 and sub.ld2>=100)
# method 3
select 
    distinct a.id, a.visit_date, a.people
from Stadium a, Stadium b, Stadium c 
where ((a.id = b.id - 1 and b.id = c.id -1) or (a.id = b.id+1 and a.id = c.id-1) or (b.id = c.id-1 and c.id = a.id -1)) and a.people >=100 and b.people>=100 and c.people>=100
order by a.id 

1097. 游戏玩法分析

# method 1
select 
    install_dt,  
    count(distinct player_id) as installs,
    round(
        ifnull(
        sum(case when datediff(event_date, install_dt)=1 then 1 else 0 end)/count(distinct player_id) 
        ,0)
    ,2) as Day1_retention 
from 
(select player_id , event_date, min(event_date) over(partition by player_id) as install_dt from Activity) sub 
group by install_dt

# method 2
select 
    b.install_dt, count(*) as installs, 
    round(count(distinct a.player_id)/count(*),2) as Day1_retention 
from
(select player_id, min(event_date) as install_dt  from Activity group by player_id) b  
left join Activity a 
on b.player_id = a.player_id and datediff(a.event_date, b.install_dt ) = 1
group by b.install_dt 

1164.指定日期的产品价格

# method 1
select product_id, new_price as price 
from Products 
where (product_id, change_date) in 
(select  product_id, max(change_date) as change_date
from Products 
where change_date <='2019-08-16'
group by product_id)
union 
select distinct product_id, 10 from Products 
where product_id not in (select product_id from Products where change_date <= '2019-08-16')

# method 2 
select p1.product_id, ifnull(p2.new_price, 10) as price 
from 
(select distinct product_id from products) p1 
left join 
(select product_id, new_price 
from Products
where (product_id, change_date) in 
(select product_id, max(change_date)
from Products
where change_date <= '2019-08-16'
group by product_id)) p2 
on p1.product_id = p2.product_id

1194. 锦标赛优胜者

# method 1  最后一个group by 是为了取出每个group_id的第一行。
select group_id, player_id 
from 
(select sub.player_id, sum(score) as score, group_id 
from 
(select first_player as player_id, sum(first_score) as score from Matches group by first_player
union all
select second_player as player_id, sum(second_score) as score from Matches group by second_player) sub 
inner join players p 
on sub.player_id = p.player_id
group by sub.player_id
order by score desc, sub.player_id) result 
group by group_id

# method 2
select group_id, player_id
from 
(select 
    group_id, player_id, 
    row_number() over(partition by group_id order by score desc, player_id asc) as rk
from 
(select 
    group_id, player_id,
    sum(
        case when first_player = player_id then first_score
        when second_player = player_id then second_score end 
    ) as score 
from Matches m
inner join Players p 
on m.second_player = p.player_id or m.first_player = p.player_id 
group by group_id,player_id
) result1
)result2 where rk = 1

1204.最后一个能进入电梯的人

# method 1
select person_name from 
(select person_name, sum(weight) over(order by turn) as sum_all 
from Queue
order by sum_all desc) sub 
where sum_all <= 1000
limit 1

# method 2
select a.person_name 
from Queue a, Queue b 
where a.turn >= b.turn 
group by a.person_id 
having sum(b.weight) <= 1000
order by a.turn desc 
limit 1

# method 3
select person_name       
from Queue q 
where (select sum(weight) from Queue where turn <= q.turn) <= 1000
order by turn desc 
limit 1

1264.页面推荐

# method 1
select distinct page_id as recommended_page from Likes 
where user_id in 
(
    select user1_id from Friendship where user2_id = 1
    union all 
    select user2_id from Friendship where user1_id = 1
)
and page_id not in (select page_id from Likes where user_id =1)

# method 2
select distinct page_id as recommended_page from Likes 
where user_id in 
(
    select (case when user1_id = 1 then user2_id
                 when user2_id = 1 then user1_id
            end
    )
    from Friendship 
    where user1_id = 1 or user2_id =1
)
and page_id not in (select page_id from Likes where user_id =1)

1285.找到连续区间的开始和结束数字

# method 1
select a.log_id as start_id, min(b.log_id) as end_id
from 
(select log_id from Logs where log_id-1 not in (select log_id from Logs)) a,    
(select log_id from Logs where log_id+1 not in (select log_id from Logs)) b 
where a.log_id <= b.log_id 
group by a.log_id

# method 2
select min(log_id) as start_id, max(log_id) as end_id  from (
    select log_id, (log_id - row_number() over(order by log_id asc)) as num from Logs 
) sub 
group by num 

1308.不同性别每日分数总计

# method 1
select gender, day, sum(score_points) over(partition by gender order by day asc) as 'total'
from Scores 

# method 2
SELECT s1.gender, s1.day, SUM(s2.score_points) AS total
FROM Scores AS s1, Scores AS s2
WHERE s1.gender = s2.gender AND s1.day >= s2.day
GROUP BY s1.gender, s1.day
ORDER BY s1.gender, s1.day;

1321. 餐厅营业额变化增长

# method 1
select 
a.visited_on, sum(b.amount) as amount, 
round(sum(b.amount)/7,2) as average_amount 
from 
(select distinct visited_on  from Customer) a 
inner join Customer b 
on datediff(a.visited_on, b.visited_on) between 0 and 6    
where a.visited_on >= (select min(visited_on) from Customer) +6
group by a.visited_on

# method 2
select  visited_on,amount,average_amount
from
(
	select 
		visited_on,
		sum(total) over(order by visited_on rows between 6 preceding and current row) as amount,
		round(avg(total) over(order by visited_on rows between 6 preceding and current row),2) as average_amount
	
	from(select visited_on,sum(amount) as total from Customer group by visited_on order by visited_on)as t

)as t3
where visited_on >= (select min(visited_on) from Customer) +6
-- where visited_on in (select t1.visited_on from Customer t1, Customer t2 where datediff(t1.visited_on, t2.visited_on)=6)

1355.活动参与者

# method 1 
select activity from Friends
group by activity
having count(*) > any(select count(*) from Friends group by activity)
and count(*) < any(select count(*) from Friends group by activity)

# method 2
select activity from Friends
group by activity
having count(*) != (select count(*) from Friends group by activity order by count(*) desc limit 1)
and count(*) != (select count(*) from Friends group by activity order by count(*) asc limit 1)

# method 3
select activity from 
(select activity, 
    rank() over(order by count(*) asc) as 'rank1',
    rank() over(order by count(*) desc) as 'rank2'
from Friends
group by activity) sub 
where sub.rank1 <> 1 and sub.rank2 <> 1

1369. 获取最近第二次的活动

# method 1
select 
    username, activity, startDate, endDate
from 
(select 
    *,
    row_number() over(partition by username order by startDate desc) as rk ,
    count(*) OVER(partition BY username) as num 
from UserActivity) sub 
where rk =2 or num =1

# method 2
select 
    u1.*
from UserActivity u1 
join UserActivity u2
using(username)
group by u1.username, u1.startdate
having sum(u2.startdate > u1.startdate) = 1 or count(u1.username) = 1

1412. 找出成绩处于中游的学生

# method 1
select 
    student_id, student_name 
from Student 
where student_id not in 
(
  select student_id 
  from Exam e 
  where score >= all(select score from Exam where exam_id = e.exam_id) or score <= all(select score from Exam where exam_id = e.exam_id)
) 
and student_id in (select student_id from Exam)

# method 2
select sub_rk.student_id,s.student_name
from 
    (
        select 
            exam_id, student_id, score, 
            if(rank() over(partition by exam_id order by score)=1,1,0) as asc_rk,
            if(rank() over(partition by exam_id order by score desc)=1,1,0) as desc_rk
        from Exam
    ) sub_rk
inner join Student s 
using(student_id)
group by sub_rk.student_id
having sum(asc_rk) = 0 and sum(desc_rk) = 0

1454. 活跃用户

# method 1
select 
	distinct l1.id, ac.name
from Logins l1
join Logins l2
on l1.id = l2.id and datediff(l2.login_date,l1.login_date) between 0 and 4
inner join Accounts ac on l1.id = ac.id
group by l1.id,l1.login_date
having count(distinct l2.login_date) >= 5

# method 2 
select id,name from Accounts 
where id in 
(select id from 
(select 
	 distinct id, login_date, 
     date_sub(login_date, INTERVAL dense_rank() over(partition by id order by login_date) DAY) as diff
from Logins) sub 
group by id,diff
having count(*) >= 5) 
order by id 

1549. 每件产品的最新订单

# method 1
select product_name, product_id, order_id, order_date
from 
(select p.product_name, o.*, rank() over(partition by o.product_id order by o.order_date desc) as 'rank' from Orders o 
inner join Products p using(product_id)) sub 
where sub.rank = 1
order by product_name, product_id, order_id

# method 2
select p.product_name, o.product_id, o.order_id, o.order_date 
from Orders o 
inner join Products p using(product_id)
where (o.product_id, o.order_date) in 
(select product_id, max(order_date) as order_date from Orders 
group by product_id)
order by p.product_name, o.product_id, o.order_id

1699. 两人之间的通话次数

# method 1
select if(from_id<to_id, from_id, to_id) as person1,
    if(from_id<to_id, to_id, from_id) as person2,
    count(*) as call_count,
    sum(duration) as total_duration 
from Calls 
group by person1, person2

# method 2
select from_id as person1,
        to_id as person2,
        count(*) as call_count,
        sum(duration) as total_duration 
from Calls 
group by if(from_id<to_id, from_id, to_id), if(from_id<to_id, to_id, from_id)

# method 3
select from_id as person1,
        to_id as person2,
        count(*) as call_count,
        sum(duration) as total_duration 
from Calls 
group by least(from_id, to_id), greatest(to_id, from_id)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值