当前位置:   article > 正文

leetcode的高频SQL50题基础版(答案和要点)_sql高级查询50道题

sql高级查询50道题

第一题:

1.可回收且低脂的产品

  1. select
  2. product_id
  3. from
  4. Products
  5. where
  6. low_fats = "Y" and recyclable = "Y"

2.寻找用户推荐人

考察SQL里面空值也是不等于2的。

即:数值不等于2或者空值。也可以用<=>表示,即not referee_id <=> 2。

  1. select
  2. name
  3. from
  4. customer
  5. where
  6. referee_id <> 2 or referee_id is NULL

3.大的国家

  1. select
  2. name,population,area
  3. from
  4. World
  5. where
  6. area >= 3000000 or population >= 25000000

4.文章浏览 I

  1. select
  2. distinct author_id as id
  3. from
  4. Views
  5. where
  6. viewer_id = author_id
  7. order by
  8. author_id

5.无效的推文

 length()中一个汉字会算3个字符,而char_length() 一个汉字算一个字符。

  1. select
  2. tweet_id
  3. from
  4. Tweets
  5. where length(content) > 15

6.使用唯一标识码替换员工ID

  1. select
  2. unique_id,name
  3. from
  4. Employees
  5. left join
  6. EmployeeUNI
  7. on
  8. Employees.id = EmployeeUNI.id

7.产品销售分析 I

  1. select
  2. product_name,year,price
  3. from
  4. Sales
  5. left join
  6. Product
  7. on
  8. Sales.product_id = Product.product_id

8.进店却未进行过交易的顾客

  1. select
  2. customer_id,
  3. count(*) count_no_trans
  4. from
  5. Visits
  6. left join
  7. Transactions
  8. on
  9. Visits.visit_id = Transactions.visit_id
  10. where
  11. Transactions.visit_id is null
  12. group by
  13. customer_id

9.上升的温度

数据库表纵向相比的思路就行转化为同表联立后做差。

日期做差函数:datediff(W1.recordDate,W2.recordDate) = 1

  1. select
  2. W1.id as id
  3. from
  4. Weather W1
  5. left join
  6. Weather W2
  7. on
  8. datediff(W1.recordDate,W2.recordDate) = 1
  9. where
  10. W1.Temperature > W2.Temperature

10.每台机器的进程平均运行时间

小数取值函数round(,3)。

这题可以采用上题的思路,自连接后进行数据判断,然后用平均函数计算一下就行,即:

  1. select
  2. a1.machine_id,
  3. round(avg(a2.timestamp - a1.timestamp),3) processing_time
  4. from
  5. Activity a1
  6. left join
  7. Activity a2
  8. on
  9. a1.machine_id = a2.machine_id and a1.process_id = a2.process_id
  10. where
  11. a1.activity_type = "start" and a2.activity_type = "end"
  12. group by
  13. machine_id

答案给了其他的思路,即采用根据activity_type字段的值来判断timestamp是否取负值,采用if函数来完成这个操作。如果数据库的不同字段存在一定关联的时候,要能够想到这样的解法可能。

  1. select
  2. machine_id,
  3. round(avg(if(activity_type='start', -timestamp, timestamp))*2, 3) processing_time
  4. from Activity
  5. group by machine_id

11.员工奖金

  1. select
  2. name,bonus
  3. from
  4. Employee
  5. left join
  6. Bonus
  7. on
  8. Employee.empId = Bonus.empId
  9. where
  10. bonus < 1000 or bonus is null

12.学生们参加各科测试的次数

笛卡尔积可以用cross join 或者join表示;

  1. select
  2. Students.student_id,student_name,Subjects.subject_name,
  3. count(Examinations.subject_name) attended_exams
  4. from
  5. Students
  6. cross join
  7. Subjects
  8. left join
  9. Examinations
  10. on
  11. Examinations.student_id = Students.student_id
  12. and
  13. Examinations.subject_name = Subjects.subject_name
  14. group by
  15. Students.student_id,subject_name
  16. order by
  17. student_id,subject_name

13.至少有5名直接下属的经理

  1. select
  2. name
  3. from(
  4. select
  5. e1.name,
  6. count(*) num
  7. from
  8. Employee e1
  9. left join
  10. Employee e2
  11. on
  12. e1.id = e2.managerId
  13. group by
  14. e1.id
  15. having
  16. num >=5)t

14.确认率

比率问题可以用MySQL的avg+if进行操作,null值会被归为0,无需ifnull。

  1. select
  2. Signups.user_id,
  3. round(avg(if(action = 'confirmed',1,0)),2) confirmation_rate
  4. from
  5. Signups
  6. left join
  7. Confirmations
  8. on
  9. Signups.user_id = Confirmations.user_id
  10. group by
  11. Signups.user_id

15.有趣的电影

  1. select
  2. id,movie,description,rating
  3. from
  4. cinema
  5. where
  6. description <> 'boring' and id%2 = 1
  7. order by
  8. rating desc

16.平均售价

能在select里面用if的就要考虑是不是取数据的时候就取少一点。

  1. select
  2. UnitsSold.product_id,
  3. round(sum(price*units)/sum(units),2) average_price
  4. from
  5. UnitsSold
  6. join
  7. Prices
  8. on
  9. UnitsSold.product_id = Prices.product_id
  10. where
  11. purchase_date between start_date and end_date
  12. group by
  13. product_id

17.项目员工 I

  1. select
  2. project_id,
  3. round(sum(experience_years)/count(*),2)
  4. average_years
  5. from
  6. Project
  7. left join
  8. Employee
  9. on
  10. Project.employee_id = Employee.employee_id
  11. group by
  12. project_id

18.各赛事的用户注册率

取一个数据库的值直接(select count(*) from Users)就行。

  1. select
  2. contest_id,
  3. round(100 * count(Register.user_id)/(select count(*) from Users),2)
  4. percentage
  5. from
  6. Register
  7. left join
  8. Users
  9. on
  10. Register.user_id = Users.user_id
  11. group by
  12. contest_id
  13. order by
  14. percentage desc,contest_id

19.查询结果的质量和占比

  1. select
  2. query_name,
  3. round(avg(rating / position),2) quality,
  4. round(100*sum(if(rating<3,1,0))/count(*),2) poor_query_percentage
  5. from
  6. Queries
  7. group by
  8. query_name

20.每月交易 I

不能直接group by的情况,最好在select部分把划分依据修改好,在group by后直接用别名划分最好。

  1. select
  2. date_format(trans_date,"%Y-%m") month,country,
  3. count(*) trans_count,
  4. sum(if(state = 'approved',1,0)) approved_count,
  5. sum(amount) trans_total_amount,
  6. sum(if(state = 'approved',amount,0)) approved_total_amount
  7. from
  8. Transactions
  9. group by
  10. month,country

21.即时食物配送 II

  1. select
  2. round(100 * sum(if(order_date = customer_pref_delivery_date,1,0))/count(*),2) immediate_percentage
  3. from
  4. Delivery
  5. where
  6. (customer_id, order_date) in (select customer_id, min(order_date)
  7. from Delivery group by customer_id)

22.游戏玩法分析 IV

当连接过的表除了需要的行外,全为null时。在分组情况下,avg(列名)可以直接得出比例。

  1. select
  2. round(avg(event_date is not null),2) fraction
  3. from
  4. (select
  5. player_id, min(event_date) as login
  6. from
  7. Activity
  8. group by
  9. player_id)t
  10. left join
  11. Activity
  12. on
  13. t.player_id = Activity.player_id and
  14. datediff(Activity.event_date, t.login) = 1

23.每位教师所教授的科目种类的数量

  1. select
  2. teacher_id, count(distinct subject_id) cnt
  3. from
  4. Teacher
  5. group by
  6. teacher_id

24.查询近30天活跃用户数

  1. select
  2. activity_date day,
  3. count(distinct user_id) active_users
  4. from
  5. Activity
  6. where
  7. activity_date between "2019-06-28" and "2019-07-27"
  8. group by
  9. activity_date

25.销售分析III

只在某个日期可以直接分组后判断最小日期和最大日期是否在这个区间(where后面不能跟聚合函数)。

  1. select
  2. Product.product_id, product_name
  3. from
  4. Product
  5. join
  6. Sales
  7. on
  8. Product.product_id = Sales.product_id
  9. group by
  10. Product.product_id
  11. having
  12. min(sale_date) >= "2019-01-01" and max(sale_date) <= "2019-03-31"

26.超过5名学生的课

  1. select
  2. class
  3. from
  4. Courses
  5. group by
  6. class
  7. having count(student) >= 5

27.求关注者的数量

  1. select
  2. user_id,
  3. count(distinct follower_id) followers_count
  4. from
  5. Followers
  6. group by
  7. user_id

28.只出现一次的最大数字

没有输出结果要输出null的情况,只需要外层嵌套一个select就行。

  1. select(
  2. select
  3. num
  4. from
  5. MyNumbers
  6. group by
  7. num
  8. having
  9. count(distinct num) = count(num)
  10. order by
  11. num desc limit 1)as num

29.买下所有产品的客户

  1. select
  2. customer_id
  3. from
  4. Customer
  5. group by
  6. customer_id
  7. having
  8. count(distinct product_key) = (select count(*) from Product)

30.每位经理的下属员工数量

  1. select
  2. Employees.reports_to employee_id,e2.name,
  3. count(*) reports_count,
  4. round(avg(Employees.age),0) average_age
  5. from
  6. Employees
  7. join
  8. Employees e2
  9. on
  10. Employees.reports_to = e2.employee_id
  11. group by
  12. Employees.reports_to
  13. having
  14. employee_id is not null
  15. order by
  16. employee_id

31.员工的直属部门

nuion可以自动去重,union all是保留重复。

  1. select
  2. employee_id,
  3. department_id
  4. from
  5. Employee
  6. group by
  7. employee_id
  8. having
  9. count(*) = 1
  10. union
  11. select
  12. employee_id,
  13. department_id
  14. from
  15. Employee
  16. where
  17. primary_flag = 'Y'
  18. group by
  19. employee_id

32.判断三角形

  1. select
  2. x,y,z,
  3. if(x+y>z and x+z>y and y+z>x, 'Yes', 'No') triangle
  4. from
  5. Triangle

33.连续出现的数字

用窗口函数lag()来解决这个问题。

  1. select
  2. distinct num ConsecutiveNums
  3. from
  4. (
  5. select
  6. id,num,
  7. lag(num,1)over(order by id) num1,
  8. lag(num,2)over(order by id) num2
  9. from
  10. Logs
  11. ) t
  12. where
  13. t.num = t.num1 and t.num1 = t.num2

34.指定日期的产品价格

思路介绍一下:

1.先取出指定日期之前的数据,然后从中再取出最大时间的。这就可以得到规定日期之前的最新数据,但是这数据不包括没有修改的数据。

2.取出全表数据,然后连接,补齐所有数据。

  1. select
  2. t1.product_id,
  3. if(t2.new_price is null,10,t2.new_price) price
  4. from
  5. (
  6. select product_id,new_price
  7. from Products
  8. group by
  9. product_id
  10. )t1
  11. left join
  12. (
  13. select
  14. product_id,
  15. new_price
  16. from
  17. Products
  18. where
  19. (product_id,change_date) in (
  20. select product_id, max(change_date)
  21. from
  22. Products
  23. where change_date <= '2019-08-16'
  24. group by
  25. product_id
  26. )
  27. )t2
  28. on
  29. t1.product_id = t2.product_id

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

用窗口函数累加,累加完成后取出累加值小于1000的,最后取出最后一行即可。

  1. select
  2. person_name
  3. from
  4. (
  5. select
  6. person_name,
  7. sum(weight) over(order by turn) as s
  8. from
  9. Queue
  10. )t
  11. where t.s <= 1000
  12. order by
  13. s desc limit 1

36.按分类统计薪水

  1. select
  2. 'Low Salary' category,
  3. count(*) accounts_count
  4. from
  5. Accounts
  6. where
  7. income < 20000
  8. union
  9. select
  10. 'Average Salary' category,
  11. count(*) accounts_count
  12. from
  13. Accounts
  14. where
  15. income >= 20000 and income <= 50000
  16. union
  17. select
  18. 'High Salary' category,
  19. count(*) accounts_count
  20. from
  21. Accounts
  22. where
  23. income > 50000

37.上级经理已离职的公司员工

提一下多个or和and相连的准则吧:condition1  OR   condition2  AND   condition3

其运算实际上是等价于:condition1 OR   (condition2 AND condition3)     //先运算and  再运算or

  1. select
  2. employee_id
  3. from
  4. Employees
  5. where
  6. manager_id not in (select employee_id from Employees) and salary < 30000
  7. order by
  8. employee_id

38.换座位

  1. select(
  2. case
  3. when id % 2 = 1 and id = (select count(*) from Seat) then id
  4. when id % 2 = 1 then id + 1
  5. else id - 1
  6. end
  7. )as id, student
  8. from
  9. Seat
  10. order by
  11. id

39.电影评分

如果 union/union all前后有 order by,limit 就需要加括号,否则语法通过不了。

  1. (select
  2. name results
  3. from
  4. MovieRating
  5. left join
  6. Users
  7. on
  8. MovieRating.user_id = Users.user_id
  9. group by
  10. MovieRating.user_id
  11. order by
  12. count(movie_id) desc, Users.name limit 1)
  13. union all
  14. (select
  15. title results
  16. from
  17. MovieRating
  18. left join
  19. Movies
  20. on
  21. MovieRating.movie_id = Movies.movie_id
  22. where
  23. MovieRating.created_at like "2020-02%"
  24. group by
  25. MovieRating.movie_id
  26. order by
  27. avg(rating) desc, Movies.title limit 1)

40.餐馆营业额变化增长

1.窗口函数range和row字段的使用。

2.表中有重复行,按天排序才行,所以用dense_rank而不能用row_number。

  1. select
  2. distinct visited_on,
  3. t.amount,
  4. t.average_amount
  5. from(
  6. select
  7. distinct visited_on,
  8. sum(amount) over(order by visited_on range interval 6 day preceding) amount,
  9. round(sum(amount) over(order by visited_on range interval 6 day preceding)/7,2) average_amount,
  10. dense_rank() over(order by visited_on) rk
  11. from
  12. Customer)t
  13. where t.rk > 6
  14. order by
  15. visited_on

41.好友申请 II :谁有最多的好友

  1. select
  2. t.requester_id id,
  3. count(*) num
  4. from(
  5. select
  6. requester_id,accepter_id,accept_date
  7. from
  8. RequestAccepted
  9. union all
  10. select
  11. accepter_id,requester_id,accept_date
  12. from
  13. RequestAccepted
  14. )t
  15. group by
  16. t.requester_id
  17. order by
  18. num desc limit 1

42.2016年的投资

多个条件判断的不能用where的情况,考虑用窗口函数。

  1. select
  2. round(sum(tiv_2016),2) tiv_2016
  3. from
  4. (
  5. select
  6. tiv_2016,
  7. count(*) over(partition by tiv_2015) c1,
  8. count(*) over(partition by lat,lon) c2
  9. from
  10. Insurance
  11. )t
  12. where
  13. t.c1>1 and t.c2 = 1

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

  1. select
  2. Department, Employee, Salary
  3. from(
  4. select
  5. Department.name Department, Employee.name Employee, Salary,
  6. dense_rank() over(partition by departmentId order by salary desc) rk
  7. from
  8. Employee
  9. join
  10. Department
  11. on
  12. Employee.departmentId = Department.id)t
  13. where t.rk <= 3

44.修复表中的名字

CONCAT 用来拼接字符串 ;LEFT 从左边截取字符 ;RIGHT 从右边截取字符;UPPER 变为大写 ; LOWER 变为小写 ;LENGTH 获取字符串长度。

  1. select
  2. user_id,
  3. concat(upper(left(name,1)),lower(right(name,length(name)-1))) name
  4. from
  5. Users
  6. order by
  7. user_id

45.患某种疾病的患者

  1. select
  2. patient_id,patient_name,conditions
  3. from
  4. Patients
  5. where
  6. conditions like "% DIAB1%" or conditions like "DIAB1%"

46.删除重复的电子邮箱

删除语句不是查询语句。

  1. delete from Person
  2. where id in (
  3. select
  4. id
  5. from(
  6. select
  7. id,
  8. row_number() over(partition by email order by id) rk
  9. from
  10. Person)t
  11. where t.rk > 1
  12. )

47.第二高的薪水

主要有这几种可能:1.如果第一高的薪水有两个,那么第二高的薪水默认没有,即为空,这样的话row_number()就不合适了;2.rank()函数会跳数,会出现没有第二高薪水的情况;3.dense_rank()比较合适,可能会输出重复的,去个重就可以解决。

  1. select
  2. (
  3. select
  4. distinct t.salary SecondHighestSalary
  5. from
  6. (select
  7. id,salary,
  8. dense_rank() over(order by salary desc) rn
  9. from
  10. Employee)t
  11. where
  12. t.rn = 2)as SecondHighestSalary

48.按日期分组销售产品

组内字符串拼接函数:group_concat(distinct product order by product separator ',')

  1. select
  2. sell_date,
  3. count(distinct product) num_sold,
  4. group_concat(distinct product order by product separator ',') products
  5. from
  6. Activities
  7. group by
  8. sell_date

49.列出指定时间段内所有的下单产品

  1. select
  2. product_name,
  3. sum(unit) unit
  4. from
  5. Orders
  6. join
  7. Products
  8. on
  9. Orders.product_id = Products.product_id
  10. where
  11. order_date like "2020-02%"
  12. group by
  13. Orders.product_id
  14. having
  15. unit >= 100

50.查找拥有有效邮箱的用户

正则表达式的应用

  1. select
  2. user_id,name,mail
  3. from
  4. Users
  5. where
  6. mail rlike '^[a-z|A-Z][0-9|A-Z|a-z|_|.|/|-]*@leetcode\\.com$'

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/843643
推荐阅读
相关标签
  

闽ICP备14008679号