3.📅

  • [177. 第N高的薪水]

考察内容:创建函数!

  1. CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
  2. BEGIN
  3. declare m INT;
  4. set m=N-1;
  5. RETURN (
  6. # Write your MySQL query statement below.
  7. select ifnull((select distinct Salary from Employee as E order by Salary desc limit m,1),null)
  8. );
  9. END
  10. CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
  11. BEGIN
  12. set n = N-1;
  13. RETURN (
  14. # Write your MySQL query statement below.
  15. select ifnull(
  16. (
  17. select distinct Salary getNthHighestSalary
  18. from Employee
  19. order by Salary desc
  20. limit n, 1
  21. ), null)
  22. );
  23. END
  24. #top Answer
  25. CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
  26. BEGIN
  27. SET N = N-1;
  28. RETURN (
  29. # Write your MySQL query statement below.
  30. SELECT
  31. salary
  32. FROM
  33. employee
  34. GROUP BY
  35. salary
  36. ORDER BY
  37. salary DESC
  38. LIMIT N, 1
  39. );
  40. END
  • [178. 分数排名]

如果两个分数相同,则两个分数排名(Rank)相同。请注意,平分后的下一个名次应该是下一个连续的整数值。换句话说,名次之间不应该有“间隔”。
知识点考察:窗口函数 over?

  1. # Write your MySQL query statement below
  2. select Score, dense_rank() over(order by Score desc) as 'Rank'
  3. from Scores
  4. order by Score desc;
  5. #可以理解
  6. select distinct a.Num as ConsecutiveNums
  7. from Logs as a,Logs as b,Logs as c
  8. where a.Num=b.Num and b.Num=c.Num and a.id=b.id-1 and b.id=c.id-1;

3.31

  • [181 连续出现的数字] ```sql

    Write your MySQL query statement below

    select distinct l1.num as ConsecutiveNums from logs l1 ,logs l2, logs l3 where
    l1.id = l2.id-1 and l2.id = l3.id-1 and l1.num= l2.num and l2.num = l3.num

top answer

SELECT DISTINCT l1.Num AS ConsecutiveNums FROM Logs AS l1 INNER JOIN Logs AS l2 ON l1.Id + 1 = l2.Id AND l1.Num = l2.Num INNER JOIN Logs AS l3 ON l1.Id + 2 = l3.Id AND l1.Num = l3.Num

  1. - [184 部门工资最高的员工]
  2. 解题思路:group by + in!!!
  3. ```sql
  4. SELECT
  5. Department.name AS 'Department',
  6. Employee.name AS 'Employee',
  7. Salary
  8. FROM
  9. Employee
  10. JOIN
  11. Department ON Employee.DepartmentId = Department.Id
  12. WHERE
  13. (Employee.DepartmentId , Salary) IN
  14. ( SELECT
  15. DepartmentId, MAX(Salary)
  16. FROM
  17. Employee
  18. GROUP BY DepartmentId
  19. )
  20. # 使用窗口函数跑一下
  21. select SELECT
  22. d.name AS 'Department',
  23. e.name AS 'Employee',
  24. Salary
  25. FROM (select *,rank_over()(partition by departmentid ,order by salary desc
  26. )as 'rank' from employee) e left join
  27. department d
  28. on e.departmentid = d.id and e.rank = 1
  29. # 窗口函数——答案
  30. select t2.Name Department, t1.Name Employee, t1.Salary Salary from
  31. (select *, rank() over(partition by DepartmentId order by Salary desc) as 'rk' from Employee) t1, Department t2
  32. where t1.rk = 1 and t1.DepartmentId = t2.Id;

  • 534 游戏玩法三

解题思路:窗口函数 sum()over(partition by order by)

  1. # Write your MySQL query statement below
  2. select player_id,event_date,sum(games_played) over (partition by player_id order by event_date )
  3. as 'games_played_so_far' from activity;
  • 550 游戏玩法四

解题思路:计算两个日期距离的天数 datediff(a,b) = 1——a是晚,b是早

  1. SELECT
  2. ROUND(COUNT(DISTINCT a.player_id) / (SELECT COUNT(DISTINCT player_id) FROM Activity), 2) AS fraction
  3. FROM
  4. Activity AS a
  5. INNER JOIN (
  6. SELECT
  7. player_id, MIN(event_date) AS first_login
  8. FROM
  9. Activity
  10. GROUP BY
  11. player_id
  12. ) AS b
  13. ON a.player_id = b.player_id AND DATEDIFF(a.event_date, b.first_login) = 1;
  14. # 使用round函数
  15. select round((
  16. select
  17. count(a1.player_id) cnt
  18. from
  19. Activity a1,
  20. (
  21. select
  22. player_id,
  23. min(event_date) event_date
  24. from Activity
  25. group by player_id
  26. ) a2
  27. where
  28. a1.player_id = a2.player_id and
  29. datediff(a1.event_date, a2.event_date) = 1
  30. ) / count(distinct a.player_id), 2) fraction
  31. from Activity a
  32. select
  33. round(
  34. (select count(*) from Activity a
  35. inner join
  36. (select player_id,min(event_date) first_date from Activity group by player_id) as b
  37. on a.player_id=b.player_id
  38. where datediff(a.event_date,b.first_date)=1)
  39. /
  40. (select count(distinct player_id) from Activity),
  41. 2)
  42. as fraction
  • 570 至少有5名直接下属

解题思路:group by ;having count() ;in

  1. select name from employee
  2. where id in
  3. (select managerid from employee group by managerid having count(managerid) >=5 )
  4. # top Answer ——添加别名可以提升检索速度?
  5. SELECT e1.Name
  6. FROM employee e1
  7. WHERE e1.Id IN(
  8. SELECT managerid
  9. FROM employee
  10. GROUP BY managerid
  11. HAVING COUNT(ManagerId) >= 5)
  12. # 使用内连接 inner join
  13. select e1.name as Name from Employee as e1
  14. left join Employee as e2
  15. on e1.Id = e2. ManagerId
  16. group by e1.Id having count(e2.ManagerId) >= 5

  • 574 当选者

解题思路:(不存在并列)使用group by+order by desc limit1

  1. select name from candidate
  2. where id = #注意该处不可以使用 in
  3. (select candidateid from vote group by candidateid
  4. # group by 不可以抛弃
  5. order by count(candidateid) desc limit 1)
  6. # top Answer
  7. select name
  8. from vote
  9. join candidate on vote.candidateid = candidate.id
  10. group by candidateid
  11. order by count(candidateid) desc
  12. limit 1
  • 578 查询回答率最高的问题

tip:组内频率

  1. # Write your MySQL query statement below
  2. select question_id as survey_log from survey_log
  3. group by question_id
  4. order by count(answer_id) desc limit 1
  5. # top Answer
  6. # Write your MySQL query statement below
  7. select question_id survey_log
  8. from survey_log
  9. group by question_id
  10. order by avg(answer_id is not null) desc
  11. limit 1
  • 580 统计各专业学生数量

解题思路:group by 执行顺序优先于 select + left join

  1. # Write your MySQL query statement below
  2. select dept_name ,count(student_id) as student_number from department d left join student s
  3. on d.dept_id = s.dept_id
  4. group by d.dept_id
  5. order by count(student_id) desc
  6. # top Answer
  • 626 交换座位

解题思路:交换数据
判断奇偶数 mod(id,2) = 1 奇数 = 0 为偶数
使用方法: case when then;if ;异或 1^1 = 0,0^1 = 1

  1. # Write your MySQL query statement below
  2. select
  3. (case
  4. when mod(id,2) = 1 and id != (select max(id)from seat)then id+1
  5. # 该位置只能使用 select语句 不可以使用count(distinct ID) or max(id)
  6. when mod(id,2) = 0 then id-1
  7. else id end ) as id ,student
  8. from seat
  9. order by id asc
  10. # Write your MySQL query statement below
  11. select
  12. (case
  13. when mod(id, 2) = 1 and id != (select max(id) from seat) then id + 1
  14. when mod(id, 2) = 0 then id - 1
  15. else id end) as id,
  16. student
  17. from seat
  18. order by id asc
  19. 作者:jun-mo-xiao-21
  20. 链接:https://leetcode-cn.com/problems/exchange-seats/solution/cha-xun-zi-ju-zhong-zhi-jie-shi-yong-case-whenlai-/
  21. 来源:力扣(LeetCode
  22. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 1270 向公司CEO回报工作的所有员工

解题思路:总共三层,选出经理的层级就OK了
主要还是学会递归

  1. #top Answer
  2. # Write your MySQL query statement below
  3. select e1.employee_id
  4. from Employees e1 left join Employees e2
  5. on e1.manager_id = e2.employee_id
  6. left join Employees e3
  7. on e2.manager_id = e3.employee_id
  8. where e3.manager_id = 1 and e1.employee_id != 1

  • 1501 可以放心投资的国家

解题思路:将phone_number 前缀提取-left join对应国家
到calls 表中联结两次,算时间!- 求均值
难点:提取phone_number 前缀:
country_code = LEFT(phone_number, 3)

  1. # 我的答案——借鉴 一位老哥的思路 ——耗时1052 ms
  2. select c.name Country from country c
  3. right join (select id,left(phone_number,3) as c_d from person) tmp
  4. on c.country_code = tmp.c_d
  5. right join calls ca
  6. on (ca.caller_id = tmp.id or ca.callee_id = tmp.id)
  7. #join条件语句可以使用or!
  8. group by c.country_code
  9. having avg(duration) > (select avg(duration) from calls)
  10. #top Answer ——耗时 731ms
  11. # Write your MySQL query statement below
  12. SELECT c.name AS country
  13. FROM Calls, Person, Country c
  14. WHERE (caller_id = id OR callee_id = id) AND country_code = LEFT(phone_number, 3)
  15. GROUP BY country_code
  16. HAVING AVG(duration) > (SELECT AVG(duration) FROM Calls);

  • 1098 小众书籍

解题思路 DATEDIFF(‘条件日期’,’变化日期’) 判定条件
注意:售卖1年的条件放在 left join on后面
如果放在where后面,1年中部分一本没卖的书籍直接被过滤了
注意left join和普通join 在on的后面跟条件的区别 left on+条件,只改变右边的值,无法改变左表的值,左表值仍然保留,没有where 的直接过滤作用 inner join 后的on + 条件,可以直接过滤条件 等同于where的作用

1、join on 和 where 选择不同,on是连接时,where是连接后筛选 2、dispatch_date条件位置的放置很关键,它必须放在on后面,如果where后面,则会将没有购买的信息过滤掉 3、如果将available_from放到on后面,则对left join 无影响,无法按条件去除信息

  1. select b.book_id,name from books b
  2. left join orders o on b.book_id = o.book_id
  3. and DATEDIFF('2019-06-23',dispatch_date) <=365
  4. where DATEDIFF('2019-05-23',available_from) > 30
  5. group by b.book_id
  6. having ifnull(sum(quantity),0) < 10