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

写一条SQL查询展示每一位用户 最近第二次 的活动,如果用户仅有一次活动,返回该活动。一个用户不能同时进行超过一项活动,以 任意 顺序返回结果。

展示效果:

  1. +------------+--------------+-------------+-------------+
  2. | username | activity | startDate | endDate |
  3. +------------+--------------+-------------+-------------+
  4. | Alice | Dancing | 2020-02-21 | 2020-02-23 |
  5. | Bob | Travel | 2020-02-11 | 2020-02-18 |
  6. +------------+--------------+-------------+-------------+

建表语句:

  1. Create table If Not Exists 81_UserActivity (username varchar(30), activity varchar(30), startDate date, endDate date);
  2. Truncate table 81_UserActivity;
  3. insert into 81_UserActivity (username, activity, startDate, endDate) values ('Alice', 'Travel', '2020-02-12', '2020-02-20');
  4. insert into 81_UserActivity (username, activity, startDate, endDate) values ('Alice', 'Dancing', '2020-02-21', '2020-02-23');
  5. insert into 81_UserActivity (username, activity, startDate, endDate) values ('Alice', 'Travel', '2020-02-24', '2020-02-28');
  6. insert into 81_UserActivity (username, activity, startDate, endDate) values ('Bob', 'Travel', '2020-02-11', '2020-02-18');

最终SQL:

  1. -- 方法一
  2. select
  3. max(u1.username) username,
  4. max(u1.activity) activity,
  5. max(u1.startdate) startdate,
  6. max(u1.enddate) enddate
  7. from
  8. 81_useractivity u1
  9. join
  10. 81_useractivity u2
  11. on
  12. u1.username = u2.username
  13. group by
  14. u1.username, u1.startdate
  15. having
  16. sum(if(u2.startdate > u1.startdate,1,0)) = 1
  17. or
  18. count(1) = 1;
  19. -- 方法二
  20. select
  21. `username`,
  22. activity,
  23. startDate,
  24. endDate
  25. from
  26. (select
  27. username,
  28. activity,
  29. startDate,
  30. endDate ,
  31. rank() over(partition by username order by startDate desc) rk,
  32. lag(startDate ,1, null) over(partition by username order by startDate ) lg
  33. from 81_UserActivity) t1
  34. where
  35. rk=2 or (rk = 1 and lg is null)

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

写一段SQL查询来展示每位用户的 唯一标识码(unique ID );如果某位员工没有唯一标识码,使用 null 填充即可。你可以以 任意 顺序返回结果表。

展示效果:

  1. +-----------+----------+
  2. | unique_id | name |
  3. +-----------+----------+
  4. | null | Alice |
  5. | null | Bob |
  6. | 2 | Meir |
  7. | 3 | Winston |
  8. | 1 | Jonathan |
  9. +-----------+----------+

建表语句:

  1. Create table If Not Exists 82_Employees (id int, name varchar(20));
  2. Create table If Not Exists 82_EmployeeUNI (id int, unique_id int);
  3. Truncate table 82_Employees;
  4. insert into 82_Employees (id, name) values ('1', 'Alice');
  5. insert into 82_Employees (id, name) values ('7', 'Bob');
  6. insert into 82_Employees (id, name) values ('11', 'Meir');
  7. insert into 82_Employees (id, name) values ('90', 'Winston');
  8. insert into 82_Employees (id, name) values ('3', 'Jonathan');
  9. Truncate table 82_EmployeeUNI;
  10. insert into 82_EmployeeUNI (id, unique_id) values ('3', '1');
  11. insert into 82_EmployeeUNI (id, unique_id) values ('11', '2');
  12. insert into 82_EmployeeUNI (id, unique_id) values ('90', '3');

最终SQL:

  1. select
  2. if(unique_id is null, null, unique_id) as unique_id,
  3. e.name
  4. from
  5. 82_Employees e
  6. left join
  7. 82_EmployeeUNI u
  8. on
  9. e.id = u.id;

83. 按年度列出销售总额

编写一段SQL查询每个产品每年的总销售额,并包含 product_id, product_name 以及 report_year 等信息。销售年份的日期介于 2018 年到 2020 年之间。你返回的结果需要按 product_id 和 report_year 排序

展示效果:

  1. +------------+--------------+-------------+--------------+
  2. | product_id | product_name | report_year | total_amount |
  3. +------------+--------------+-------------+--------------+
  4. | 1 | LC Phone | 2019 | 3500 |
  5. | 2 | LC T-Shirt | 2018 | 310 |
  6. | 2 | LC T-Shirt | 2019 | 3650 |
  7. | 2 | LC T-Shirt | 2020 | 10 |
  8. | 3 | LC Keychain | 2019 | 31 |
  9. | 3 | LC Keychain | 2020 | 31 |
  10. +------------+--------------+-------------+--------------+
  11. LC Phone 2019-01-25 2019-02-28 期间销售,该产品销售时间总计35天。销售总额 35*100 = 3500
  12. LC T-shirt 2018-12-01 2020-01-01 期间销售,该产品在2018年、2019年、2020年的销售时间分别是31天、365天、1天,2018年、2019年、2020年的销售总额分别是31*10=310365*10=36501*10=10
  13. LC Keychain 2019-12-01 2020-01-31 期间销售,该产品在2019年、2020年的销售时间分别是:31天、31天,2019年、2020年的销售总额分别是31*1=3131*1=31

建表语句:

  1. Create table If Not Exists 83_Product (product_id int, product_name varchar(30));
  2. Create table If Not Exists 83_Sales (product_id varchar(30), period_start date, period_end date, average_daily_sales int);
  3. Truncate table 83_Product;
  4. insert into 83_Product (product_id, product_name) values ('1', 'LC Phone ');
  5. insert into 83_Product (product_id, product_name) values ('2', 'LC T-Shirt');
  6. insert into 83_Product (product_id, product_name) values ('3', 'LC Keychain');
  7. Truncate table 83_Sales;
  8. insert into 83_Sales (product_id, period_start, period_end, average_daily_sales) values ('1', '2019-01-25', '2019-02-28', '100');
  9. insert into 83_Sales (product_id, period_start, period_end, average_daily_sales) values ('2', '2018-12-01', '2020-01-01', '10');
  10. insert into 83_Sales (product_id, period_start, period_end, average_daily_sales) values ('3', '2019-12-01', '2020-01-31', '1');

最终SQL:

  1. (select
  2. s1.product_id,
  3. product_name,
  4. '2018' as 'report_year',
  5. if(period_start<'2019-01-01',(datediff(
  6. if(period_end<'2019-01-01', period_end, date('2018-12-31')),
  7. if(period_start>='2018-01-01', period_start, date('2018-01-01'))
  8. )+1
  9. ) * average_daily_sales, 0) as total_amount
  10. from
  11. 83_Sales as s1
  12. join
  13. 83_Product as p1
  14. on
  15. s1.product_id = p1.product_id
  16. having
  17. total_amount>0 )
  18. union
  19. (select
  20. s2.product_id,
  21. product_name,
  22. '2019' as 'report_year',
  23. if( period_start<'2020-01-01', (datediff(
  24. if(period_end<'2020-01-01', period_end, date('2019-12-31')), if(period_start>='2019-01-01', period_start, date('2019-01-01'))
  25. )+1
  26. ) * average_daily_sales , 0) as total_amount
  27. from
  28. 83_Sales as s2
  29. join
  30. 83_Product as p2
  31. on
  32. s2.product_id = p2.product_id
  33. having total_amount>0)
  34. union
  35. (select
  36. s3.product_id,
  37. product_name,
  38. '2020' as 'report_year',
  39. (datediff(
  40. if(period_end<'2021-01-01', period_end, date('2020-12-31')),
  41. if(period_start>='2020-01-01', period_start, date('2020-01-01'))
  42. )+1
  43. ) * average_daily_sales as total_amount
  44. from
  45. 83_Sales as s3
  46. join
  47. 83_Product as p3
  48. on
  49. s3.product_id = p3.product_id
  50. having total_amount>0 )
  51. order by product_id, report_year

84. 股票的资本损益

编写一个SQL查询来报告每支股票的资本损益。股票的资本损益是一次或多次买卖股票后的全部收益或损失。以任意顺序返回结果即可。

展示效果:

  1. +---------------+-------------------+
  2. | stock_name | capital_gain_loss |
  3. +---------------+-------------------+
  4. | Corona Masks | 9500 |
  5. | Leetcode | 8000 |
  6. | Handbags | -23000 |
  7. +---------------+-------------------+
  8. Leetcode 股票在第一天以1000美元的价格买入,在第五天以9000美元的价格卖出。资本收益=9000-1000=8000美元。
  9. Handbags 股票在第17天以30000美元的价格买入,在第29天以7000美元的价格卖出。资本损失=7000-30000=-23000美元。
  10. Corona Masks 股票在第1天以10美元的价格买入,在第3天以1010美元的价格卖出。在第4天以1000美元的价格再次购买,在第5天以500美元的价格出售。最后,它在第6天以1000美元的价格被买走,在第10天以10000美元的价格被卖掉。资本损益是每次(’Buy'->'Sell')操作资本收益或损失的和=(1010-10)+(500-1000)+(10000-1000)=1000-500+9000=9500美元。
  1. Create Table If Not Exists 84_Stocks(stock_name varchar(15),operation ENUM('Sell', 'Buy'),operation_day int, price int);
  2. Truncate table 84_Stocks;
  3. insert into 84_Stocks (stock_name, operation, operation_day, price) values ('Leetcode', 'Buy', '1', '1000');
  4. insert into 84_Stocks (stock_name, operation, operation_day, price) values ('Corona Masks', 'Buy', '2', '10');
  5. insert into 84_Stocks (stock_name, operation, operation_day, price) values ('Leetcode', 'Sell', '5', '9000');
  6. insert into 84_Stocks (stock_name, operation, operation_day, price) values ('Handbags', 'Buy', '17', '30000');
  7. insert into 84_Stocks (stock_name, operation, operation_day, price) values ('Corona Masks', 'Sell', '3', '1010');
  8. insert into 84_Stocks (stock_name, operation, operation_day, price) values ('Corona Masks', 'Buy', '4', '1000');
  9. insert into 84_Stocks (stock_name, operation, operation_day, price) values ('Corona Masks', 'Sell', '5', '500');
  10. insert into 84_Stocks (stock_name, operation, operation_day, price) values ('Corona Masks', 'Buy', '6', '1000');
  11. insert into 84_Stocks (stock_name, operation, operation_day, price) values ('Handbags', 'Sell', '29', '7000');
  12. insert into 84_Stocks (stock_name, operation, operation_day, price) values ('Corona Masks', 'Sell', '10', '10000');

最终SQL:

  1. -- 方法一
  2. select
  3. s2.stock_name,
  4. s2.sum_sell - s1.sum_buy as capital_gain_loss
  5. from
  6. (select
  7. stock_name,
  8. sum(if(operation='Buy',price,0)) as sum_buy,
  9. sum(if(operation='Sell',price,0)) as sum_sell
  10. from
  11. 84_stocks
  12. group by
  13. stock_name, operation) s1
  14. join
  15. (select
  16. stock_name,
  17. sum(if(operation='Buy',price,0)) as sum_buy,
  18. sum(if(operation='Sell',price,0)) as sum_sell
  19. from
  20. 84_stocks
  21. group by
  22. stock_name, operation) s2
  23. on
  24. s1.stock_name = s2.stock_name
  25. where
  26. s1.sum_buy <> 0
  27. and
  28. s2.sum_buy = 0;
  29. -- 方法二
  30. select
  31. stock_name,sell-buy capital_gain_loss
  32. from
  33. (select
  34. stock_name,
  35. sum(if(operation='Buy', price,0))over(partition by stock_name ) buy,
  36. sum(if(operation='Sell',price,0))over(partition by stock_name) sell
  37. from
  38. 84_Stocks s )t1
  39. group by
  40. stock_name,buy,sell;

85. 购买了产品A和B却没有购买产品C的顾客

请你设计 SQL 查询来报告购买了产品 A 和产品 B 却没有购买产品 C 的顾客的 ID 和姓名( customer_idcustomer_name ),我们将基于此结果为他们推荐产品 C 。
您返回的查询结果需要按照 customer_id 排序

展示效果:

  1. +-------------+---------------+
  2. | customer_id | customer_name |
  3. +-------------+---------------+
  4. | 3 | Elizabeth |
  5. +-------------+---------------+

建表语句:

  1. Create table If Not Exists 85_Customers (customer_id int, customer_name varchar(30));
  2. Create table If Not Exists 85_Orders (order_id int, customer_id int, product_name varchar(30));
  3. Truncate table 85_Customers;
  4. insert into 85_Customers (customer_id, customer_name) values ('1', 'Daniel');
  5. insert into 85_Customers (customer_id, customer_name) values ('2', 'Diana');
  6. insert into 85_Customers (customer_id, customer_name) values ('3', 'Elizabeth');
  7. insert into 85_Customers (customer_id, customer_name) values ('4', 'Jhon');
  8. Truncate table 85_Orders;
  9. insert into 85_Orders (order_id, customer_id, product_name) values ('10', '1', 'A');
  10. insert into 85_Orders (order_id, customer_id, product_name) values ('20', '1', 'B');
  11. insert into 85_Orders (order_id, customer_id, product_name) values ('30', '1', 'D');
  12. insert into 85_Orders (order_id, customer_id, product_name) values ('40', '1', 'C');
  13. insert into 85_Orders (order_id, customer_id, product_name) values ('50', '2', 'A');
  14. insert into 85_Orders (order_id, customer_id, product_name) values ('60', '3', 'A');
  15. insert into 85_Orders (order_id, customer_id, product_name) values ('70', '3', 'B');
  16. insert into 85_Orders (order_id, customer_id, product_name) values ('80', '3', 'D');
  17. insert into 85_Orders (order_id, customer_id, product_name) values ('90', '4', 'C');

最终SQL:

  1. select
  2. o.customer_id,
  3. customer_name
  4. from
  5. 85_Orders o
  6. left join
  7. 85_Customers c
  8. on
  9. o.customer_id=c.customer_id
  10. group by
  11. customer_id
  12. having
  13. sum(product_name ='A')>=1
  14. and
  15. sum(product_name='B')>=1
  16. and
  17. sum(product_name='C')=0;

86. 排名靠前的旅行者

写一段 SQL , 报告每个用户的旅行距离。返回的结果表单, 以 travelled_distance 降序排列, 如果有两个或者更多的用户旅行了相同的距离, 那么再以 name 升序排列.

展示效果:

  1. +----------+--------------------+
  2. | name | travelled_distance |
  3. +----------+--------------------+
  4. | Elvis | 450 |
  5. | Lee | 450 |
  6. | Bob | 317 |
  7. | Jonathan | 312 |
  8. | Alex | 222 |
  9. | Alice | 120 |
  10. | Donald | 0 |
  11. +----------+--------------------+
  12. Elvis Lee 旅行了 450 英里, Elvis 是排名靠前的旅行者, 因为他的名字在字母表上的排序比 Lee 更小.
  13. Bob, Jonathan, Alex Alice 只有一次行程, 我们只按此次行程的全部距离对他们排序.
  14. Donald 没有任何行程, 他的旅行距离为 0.

建表语句:

  1. Create Table If Not Exists 86_Users (id int, name varchar(30));
  2. Create Table If Not Exists 86_Rides (id int, user_id int, distance int);
  3. Truncate table 86_Users;
  4. insert into 86_Users (id, name) values ('1', 'Alice');
  5. insert into 86_Users (id, name) values ('2', 'Bob');
  6. insert into 86_Users (id, name) values ('3', 'Alex');
  7. insert into 86_Users (id, name) values ('4', 'Donald');
  8. insert into 86_Users (id, name) values ('7', 'Lee');
  9. insert into 86_Users (id, name) values ('13', 'Jonathan');
  10. insert into 86_Users (id, name) values ('19', 'Elvis');
  11. Truncate table 86_Rides;
  12. insert into 86_Rides (id, user_id, distance) values ('1', '1', '120');
  13. insert into 86_Rides (id, user_id, distance) values ('2', '2', '317');
  14. insert into 86_Rides (id, user_id, distance) values ('3', '3', '222');
  15. insert into 86_Rides (id, user_id, distance) values ('4', '7', '100');
  16. insert into 86_Rides (id, user_id, distance) values ('5', '13', '312');
  17. insert into 86_Rides (id, user_id, distance) values ('6', '19', '50');
  18. insert into 86_Rides (id, user_id, distance) values ('7', '7', '120');
  19. insert into 86_Rides (id, user_id, distance) values ('8', '19', '400');
  20. insert into 86_Rides (id, user_id, distance) values ('9', '7', '230');

最终SQL:

  1. select
  2. name,
  3. sum(ifnull(distance,0)) travelled_distance
  4. from
  5. 86_Users u
  6. left join
  7. 86_Rides r
  8. on
  9. u.id = r.user_id
  10. group by
  11. name
  12. order by
  13. travelled_distance desc, name;

87. 查找成绩处于中游的学生

写一个 SQL 语句,找出在所有测验中都处于中游的学生 (student_id, student_name)。成绩处于中游的学生是指至少参加了一次测验, 且得分既不是最高分也不是最低分的学生。不要返回从来没有参加过测验的学生。返回结果表按照 student_id 排序。

展示效果:

  1. +-------------+---------------+
  2. | student_id | student_name |
  3. +-------------+---------------+
  4. | 2 | Jade |
  5. +-------------+---------------+
  6. 对于测验 1: 学生 1 3 分别获得了最低分和最高分。
  7. 对于测验 2: 学生 1 既获得了最高分, 也获得了最低分。
  8. 对于测验 3 4: 学生 1 4 分别获得了最低分和最高分。
  9. 学生 2 5 没有在任一场测验中获得了最高分或者最低分。
  10. 因为学生 5 从来没有参加过任何测验, 所以他被排除于结果表。
  11. 由此, 我们仅仅返回学生 2 的信息。

建表语句:

  1. Create table If Not Exists 87_Student (student_id int, student_name varchar(30));
  2. Create table If Not Exists 87_Exam (exam_id int, student_id int, score int);
  3. Truncate table 87_Student;
  4. insert into 87_Student (student_id, student_name) values ('1', 'Daniel');
  5. insert into 87_Student (student_id, student_name) values ('2', 'Jade');
  6. insert into 87_Student (student_id, student_name) values ('3', 'Stella');
  7. insert into 87_Student (student_id, student_name) values ('4', 'Jonathan');
  8. insert into 87_Student (student_id, student_name) values ('5', 'Will');
  9. Truncate table 87_Exam;
  10. insert into 87_Exam (exam_id, student_id, score) values ('10', '1', '70');
  11. insert into 87_Exam (exam_id, student_id, score) values ('10', '2', '80');
  12. insert into 87_Exam (exam_id, student_id, score) values ('10', '3', '90');
  13. insert into 87_Exam (exam_id, student_id, score) values ('20', '1', '80');
  14. insert into 87_Exam (exam_id, student_id, score) values ('30', '1', '70');
  15. insert into 87_Exam (exam_id, student_id, score) values ('30', '3', '80');
  16. insert into 87_Exam (exam_id, student_id, score) values ('30', '4', '90');
  17. insert into 87_Exam (exam_id, student_id, score) values ('40', '1', '60');
  18. insert into 87_Exam (exam_id, student_id, score) values ('40', '2', '70');
  19. insert into 87_Exam (exam_id, student_id, score) values ('40', '4', '80');

最终SQL:

  1. select
  2. student_id,
  3. student_name
  4. from
  5. 87_student
  6. where
  7. student_id not in(
  8. select
  9. s1.student_id
  10. from
  11. 87_student s1
  12. left join
  13. 87_exam e1
  14. on
  15. s1.student_id = e1.student_id
  16. join
  17. (select max(score) max_score, min(score) min_score from 87_Exam) m
  18. on
  19. e1.score = m.max_score
  20. or
  21. e1.score = m.min_score
  22. or
  23. e1.score is null);
  24. -- 方法二
  25. select
  26. e.student_id,
  27. student_name
  28. from
  29. 87_Exam e
  30. left join
  31. 87_Student s
  32. on
  33. e.student_id=s.student_id
  34. where
  35. e.student_id not in(select
  36. student_id
  37. from
  38. (select
  39. student_id,
  40. rank() over(partition by exam_id order by score desc) rkmax,
  41. rank() over(partition by exam_id order by score ) rkmin
  42. from
  43. 87_Exam )t1
  44. where
  45. rkmax = 1 or rkmin =1 )
  46. group by
  47. e.student_id,
  48. student_name
  49. order by
  50. e.student_id;

88. 净现值查询

写一个 SQL, 找到 Queries 表中每一次查询的净现值,结果表没有顺序要求.

展示效果:

  1. +------+--------+--------+
  2. | id | year | npv |
  3. +------+--------+--------+
  4. | 1 | 2019 | 113 |
  5. | 2 | 2008 | 121 |
  6. | 3 | 2009 | 12 |
  7. | 7 | 2018 | 0 |
  8. | 7 | 2019 | 0 |
  9. | 7 | 2020 | 30 |
  10. | 13 | 2019 | 40 |
  11. +------+--------+--------+
  12. (7, 2018)的净现值不在 NPV 表中, 我们把它看作是 0.
  13. 所有其它查询的净现值都能在 NPV 表中找到.
  1. Create Table If Not Exists 88_NPV (id int, year int, npv int);
  2. Create Table If Not Exists 88_Queries (id int, year int);
  3. Truncate table 88_NPV;
  4. insert into 88_NPV (id, year, npv) values ('1', '2018', '100');
  5. insert into 88_NPV (id, year, npv) values ('7', '2020', '30');
  6. insert into 88_NPV (id, year, npv) values ('13', '2019', '40');
  7. insert into 88_NPV (id, year, npv) values ('1', '2019', '113');
  8. insert into 88_NPV (id, year, npv) values ('2', '2008', '121');
  9. insert into 88_NPV (id, year, npv) values ('3', '2009', '21');
  10. insert into 88_NPV (id, year, npv) values ('11', '2020', '99');
  11. insert into 88_NPV (id, year, npv) values ('7', '2019', '0');
  12. Truncate table 88_Queries;
  13. insert into 88_Queries (id, year) values ('1', '2019');
  14. insert into 88_Queries (id, year) values ('2', '2008');
  15. insert into 88_Queries (id, year) values ('3', '2009');
  16. insert into 88_Queries (id, year) values ('7', '2018');
  17. insert into 88_Queries (id, year) values ('7', '2019');
  18. insert into 88_Queries (id, year) values ('7', '2020');
  19. insert into 88_Queries (id, year) values ('13', '2019');

最终SQL:

  1. select
  2. q.id,
  3. q.year,
  4. ifnull(npv,0) npv
  5. from
  6. 88_Queries q
  7. left join
  8. 88_NPV n
  9. on
  10. q.id = n.id
  11. and
  12. q.year = n.year;

89. 制作会话柱状图

你想知道用户在你的 app 上的访问时长情况。因此决定统计访问时长区间分别为 “[0-5>”, “[5-10>”, “[10-15>” 和 “15 or more” (单位:分钟)的会话数量,并以此绘制柱状图。

写一个SQL查询来报告(访问时长区间,会话总数)。结果可用任何顺序呈现。

展示效果:

  1. +--------------+--------------+
  2. | bin | total |
  3. +--------------+--------------+
  4. | [0-5> | 3 |
  5. | [5-10> | 1 |
  6. | [10-15> | 0 |
  7. | 15 or more | 1 |
  8. +--------------+--------------+
  9. 对于 session_id 12 3 ,它们的访问时间大于等于 0 分钟且小于 5 分钟。
  10. 对于 session_id 4,它的访问时间大于等于 5 分钟且小于 10 分钟。
  11. 没有会话的访问时间大于等于 10 分钟且小于 15 分钟。
  12. 对于 session_id 5, 它的访问时间大于等于 15 分钟。
  1. Create table If Not Exists 89_Sessions (session_id int, duration int);
  2. Truncate table 89_Sessions;
  3. insert into 89_Sessions (session_id, duration) values ('1', '30');
  4. insert into 89_Sessions (session_id, duration) values ('2', '199');
  5. insert into 89_Sessions (session_id, duration) values ('3', '299');
  6. insert into 89_Sessions (session_id, duration) values ('4', '580');
  7. insert into 89_Sessions (session_id, duration) values ('5', '1000');

最终SQL:

  1. -- 方法一
  2. select '[0-5>' as bin, count(*) as total from 89_Sessions where duration/60>=0 and duration/60<5
  3. union
  4. select '[5-10>' as bin, count(*) as total from 89_Sessions where duration/60>=5 and duration/60<10
  5. union
  6. select '[10-15>' as bin, count(*) as total from 89_Sessions where duration/60>=10 and duration/60<15
  7. union
  8. select '15 or more'as bin, count(*) as total from 89_Sessions where duration/60>=15
  9. -- 方法二
  10. select a.bin, count(b.bin) as total
  11. from
  12. (select '[0-5>' as bin union select '[5-10>' as bin union select '[10-15>' as bin union select '15 or more' as bin)a
  13. left join
  14. (select case
  15. when duration < 300 then '[0-5>'
  16. when duration >= 300 and duration < 600 then '[5-10>'
  17. when duration >= 600 and duration < 900 then '[10-15>'
  18. else '15 or more'
  19. end bin
  20. from 89_Sessions
  21. )b
  22. on a.bin = b.bin
  23. group by a.bin

90. 计算布尔表达式的值

写一个 SQL 查询, 以计算表 Expressions 中的布尔表达式,返回的结果表没有顺序要求.

展示效果:

  1. +--------------+----------+---------------+-------+
  2. | left_operand | operator | right_operand | value |
  3. +--------------+----------+---------------+-------+
  4. | x | > | y | false |
  5. | x | < | y | true |
  6. | x | = | y | false |
  7. | y | > | x | true |
  8. | y | < | x | false |
  9. | x | = | x | true |
  10. +--------------+----------+---------------+-------+

建表语句:

  1. Create Table If Not Exists 90_Variables (name varchar(3), value int);
  2. Create Table If Not Exists 90_Expressions (left_operand varchar(3), operator ENUM('>', '<', '='), right_operand varchar(3));
  3. Truncate table 90_Variables;
  4. insert into 90_Variables (name, value) values ('x', '66');
  5. insert into 90_Variables (name, value) values ('y', '77');
  6. Truncate table 90_Expressions;
  7. insert into 90_Expressions (left_operand, operator, right_operand) values ('x', '>', 'y');
  8. insert into 90_Expressions (left_operand, operator, right_operand) values ('x', '<', 'y');
  9. insert into 90_Expressions (left_operand, operator, right_operand) values ('x', '=', 'y');
  10. insert into 90_Expressions (left_operand, operator, right_operand) values ('y', '>', 'x');
  11. insert into 90_Expressions (left_operand, operator, right_operand) values ('y', '<', 'x');
  12. insert into 90_Expressions (left_operand, operator, right_operand) values ('x', '=', 'x');

最终SQL:

  1. select
  2. e.left_operand,
  3. e.operator,
  4. e.right_operand,
  5. case e.operator
  6. when '>' then if(v1.value>v2.value,'true','false')
  7. when '<' then if(v1.value<v2.value,'true','false')
  8. else if(v1.value=v2.value,'true','false')
  9. end value
  10. from
  11. 90_Expressions e
  12. left join
  13. 90_Variables v1
  14. on
  15. v1.name = e.left_operand
  16. left join
  17. 90_Variables v2
  18. on
  19. v2.name = e.right_operand;

91. 苹果和桔子

写一个 SQL 查询, 报告每一天 苹果桔子 销售的数目的差异.返回的结果表, 按照格式为 (‘YYYY-MM-DD’) 的 sale_date 排序.

查询结果表如下例所示:

  1. +------------+--------------+
  2. | sale_date | diff |
  3. +------------+--------------+
  4. | 2020-05-01 | 2 |
  5. | 2020-05-02 | 0 |
  6. | 2020-05-03 | 20 |
  7. | 2020-05-04 | -1 |
  8. +------------+--------------+
  9. 2020-05-01, 卖了 10 个苹果 8 个桔子 (差异为 10 - 8 = 2).
  10. 2020-05-02, 卖了 15 个苹果 15 个桔子 (差异为 15 - 15 = 0).
  11. 2020-05-03, 卖了 20 个苹果 0 个桔子 (差异为 20 - 0 = 20).
  12. 2020-05-04, 卖了 15 个苹果 16 个桔子 (差异为 15 - 16 = -1).
  1. Create table If Not Exists 91_Sales (sale_date date, fruit ENUM('apples', 'oranges'), sold_num int);
  2. Truncate table 91_Sales;
  3. insert into 91_Sales (sale_date, fruit, sold_num) values ('2020-05-01', 'apples', '10');
  4. insert into 91_Sales (sale_date, fruit, sold_num) values ('2020-05-01', 'oranges', '8');
  5. insert into 91_Sales (sale_date, fruit, sold_num) values ('2020-05-02', 'apples', '15');
  6. insert into 91_Sales (sale_date, fruit, sold_num) values ('2020-05-02', 'oranges', '15');
  7. insert into 91_Sales (sale_date, fruit, sold_num) values ('2020-05-03', 'apples', '20');
  8. insert into 91_Sales (sale_date, fruit, sold_num) values ('2020-05-03', 'oranges', '0');
  9. insert into 91_Sales (sale_date, fruit, sold_num) values ('2020-05-04', 'apples', '15');
  10. insert into 91_Sales (sale_date, fruit, sold_num) values ('2020-05-04', 'oranges', '16');
  1. -- 方法一
  2. select
  3. s1.sale_date,
  4. s1.sold_num - s2.sold_num as diff
  5. from
  6. 91_Sales s1
  7. join
  8. 91_Sales s2
  9. on
  10. s1.sale_date = s2.sale_date
  11. and
  12. s1.fruit <> s2.fruit
  13. and
  14. s1.fruit <> 'oranges';
  15. -- 方法二
  16. select
  17. sale_date,
  18. sold_num - ld as diff
  19. from
  20. (select
  21. sale_date,
  22. sold_num,
  23. fruit,
  24. lead(sold_num ,1,null) over(partition by sale_date ) ld
  25. from 91_Sales )t1
  26. where
  27. fruit='apples';

92. 活跃用户

写一个 SQL 查询, 找到活跃用户的 id 和 name,活跃用户是指那些至少连续 5 天登录账户的用户。返回的结果表按照 id 排序.

展示数据:

  1. +----+----------+
  2. | id | name |
  3. +----+----------+
  4. | 7 | Jonathan |
  5. +----+----------+
  6. id = 1 的用户 Winston 仅仅在不同的 2 天内登录了 2 次, 所以, Winston 不是活跃用户.
  7. id = 7 的用户 Jonathon 在不同的 6 天内登录了 7 次, , 6 天中有 5 天是连续的, 所以, Jonathan 是活跃用户.

建表语句:

  1. Create table If Not Exists 92_Accounts (id int, name varchar(10));
  2. Create table If Not Exists 92_Logins (id int, login_date date);
  3. Truncate table 92_Accounts;
  4. insert into 92_Accounts (id, name) values ('1', 'Winston');
  5. insert into 92_Accounts (id, name) values ('7', 'Jonathan');
  6. Truncate table 92_Logins;
  7. insert into 92_Logins (id, login_date) values ('7', '2020-05-30');
  8. insert into 92_Logins (id, login_date) values ('1', '2020-05-30');
  9. insert into 92_Logins (id, login_date) values ('7', '2020-05-31');
  10. insert into 92_Logins (id, login_date) values ('7', '2020-06-01');
  11. insert into 92_Logins (id, login_date) values ('7', '2020-06-02');
  12. insert into 92_Logins (id, login_date) values ('7', '2020-06-02');
  13. insert into 92_Logins (id, login_date) values ('7', '2020-06-03');
  14. insert into 92_Logins (id, login_date) values ('1', '2020-06-07');
  15. insert into 92_Logins (id, login_date) values ('7', '2020-06-10');

最终SQL:

  1. -- 方法一
  2. select
  3. distinct a.id,
  4. a.name
  5. from
  6. 92_Accounts a,
  7. 92_logins l1
  8. where
  9. a.id=l1.id
  10. and
  11. (select
  12. count(distinct l2.login_date)
  13. from
  14. 92_logins l2
  15. where
  16. l1.id=l2.id
  17. and
  18. datediff(l1.login_date,l2.login_date) between 0 and 4
  19. )>=5
  20. order by id;
  21. -- 方法二
  22. select
  23. distinct a.id, a.name
  24. from
  25. 92_Accounts a
  26. join
  27. 92_Logins l1
  28. using(id)
  29. join
  30. 92_Logins l2
  31. on
  32. l1.id = l2.id
  33. and
  34. datediff(l2.login_date, l1.login_date) between 0 and 4
  35. group by
  36. a.id, a.name, l1.login_date
  37. having
  38. count(distinct l2.login_date) = 5;
  39. -- 方法三
  40. select
  41. t3.id,name
  42. from
  43. (select
  44. distinct id
  45. from
  46. (select
  47. id,
  48. login_date,
  49. lead(login_date,4,null) over(partition by id order by login_date) ld
  50. from
  51. (select
  52. id,
  53. login_date
  54. from
  55. 92_Logins
  56. group by
  57. id,login_date
  58. )t1
  59. )t2
  60. where datediff(ld,login_date)=4
  61. )t3
  62. left join
  63. 92_Accounts a
  64. on
  65. t3.id = a.id;

93. 矩形面积

写一个 SQL 语句, 报告由表中任意两点可以形成的所有可能的矩形.

结果表中的每一行包含三列 (p1, p2, area) 如下:

  • p1p2 是矩形两个对角的 id 且 p1 < p2.
  • 矩形的面积由列 area 表示.

请按照面积大小降序排列,如果面积相同的话, 则按照 p1 和 p2 升序对结果表排序

  1. +----------+-------------+-------------+
  2. | p1 | p2 | area |
  3. +----------+-------------+-------------+
  4. | 2 | 3 | 6 |
  5. | 1 | 2 | 2 |
  6. +----------+-------------+-------------+
  7. p1 应该小于 p2 并且面积大于 0.
  8. p1 = 1 p2 = 2 时, 面积等于 |2-4| * |8-7| = 2.
  9. p1 = 2 p2 = 3 时, 面积等于 |4-2| * |7-10| = 6.
  10. p1 = 1 p2 = 3 时, 是不可能为矩形的, 因为面积等于 0.
  1. Create table If Not Exists 93_Points (id int, x_value int, y_value int);
  2. Truncate table 93_Points;
  3. insert into 93_Points (id, x_value, y_value) values ('1', '2', '8');
  4. insert into 93_Points (id, x_value, y_value) values ('2', '4', '7');
  5. insert into 93_Points (id, x_value, y_value) values ('3', '2', '10');

最终SQL:

  1. select
  2. a.id P1,
  3. b.id P2,
  4. abs(a.x_value-b.x_value)*abs(a.y_value-b.y_value) as area
  5. from
  6. Points a,Points b
  7. where
  8. a.id<b.id
  9. and
  10. a.x_value != b.x_value
  11. and
  12. a.y_value != b.y_value
  13. order by
  14. area desc,P1 ,P2

94. 计算税后工资

写一条查询 SQL 来查找每个员工的税后工资

每个公司的税率计算依照以下规则

  • 如果这个公司员工最高工资不到 1000 ,税率为 0%
  • 如果这个公司员工最高工资在 1000 到 10000 之间,税率为 24%
  • 如果这个公司员工最高工资大于 10000 ,税率为 49%

按任意顺序返回结果,税后工资结果取整

结果表格式如下例所示:

  1. +------------+-------------+---------------+--------+
  2. | company_id | employee_id | employee_name | salary |
  3. +------------+-------------+---------------+--------+
  4. | 1 | 1 | Tony | 1020 |
  5. | 1 | 2 | Pronub | 10863 |
  6. | 1 | 3 | Tyrrox | 5508 |
  7. | 2 | 1 | Pam | 300 |
  8. | 2 | 7 | Bassem | 450 |
  9. | 2 | 9 | Hermione | 700 |
  10. | 3 | 7 | Bocaben | 76 |
  11. | 3 | 2 | Ognjen | 1672 |
  12. | 3 | 13 | Nyancat | 2508 |
  13. | 3 | 15 | Morninngcat | 5911 |
  14. +------------+-------------+---------------+--------+
  15. 对于公司 1 ,最高工资是 21300 ,其每个员工的税率为 49%
  16. 对于公司 2 ,最高工资是 700 ,其每个员工税率为 0%
  17. 对于公司 3 ,最高工资是 7777 ,其每个员工税率是 24%
  18. 税后工资计算 = 工资 - ( 税率 / 100)*工资
  19. 对于上述案例,Morninngcat 的税后工资 = 7777 - 7777 * ( 24 / 100) = 7777 - 1866.48 = 5910.52 ,取整为 5911
Create table If Not Exists 94_Salaries (company_id int, employee_id int, employee_name varchar(13), salary int);
Truncate table 94_Salaries;
insert into 94_Salaries (company_id, employee_id, employee_name, salary) values ('1', '1', 'Tony', '2000');
insert into 94_Salaries (company_id, employee_id, employee_name, salary) values ('1', '2', 'Pronub', '21300');
insert into 94_Salaries (company_id, employee_id, employee_name, salary) values ('1', '3', 'Tyrrox', '10800');
insert into 94_Salaries (company_id, employee_id, employee_name, salary) values ('2', '1', 'Pam', '300');
insert into 94_Salaries (company_id, employee_id, employee_name, salary) values ('2', '7', 'Bassem', '450');
insert into 94_Salaries (company_id, employee_id, employee_name, salary) values ('2', '9', 'Hermione', '700');
insert into 94_Salaries (company_id, employee_id, employee_name, salary) values ('3', '7', 'Bocaben', '100');
insert into 94_Salaries (company_id, employee_id, employee_name, salary) values ('3', '2', 'Ognjen', '2200');
insert into 94_Salaries (company_id, employee_id, employee_name, salary) values ('3', '13', 'Nyancat', '3300');
insert into 94_Salaries (company_id, employee_id, employee_name, salary) values ('3', '15', 'Morninngcat', '7777');

最终SQL:

-- 方法一
select 
     s1.company_id,
     s1.employee_id,
     s1.employee_name,
     round(case
               when m.max_salary<1000 then salary
               when m.maxsalary<10000 then salary*(1-0.24)
               else salary*(1-0.49)
           end ,0) salary
from
     94_Salaries s1
left join
    (select 
           s2.company_id,
           max(s2.salary) max_salary
     from
           94_Salaries s2
     group by
           company_id
     ) m
on 
     m.company_id = s1.conpany_id;

-- 方法二
select 
     company_id,
     employee_id,
     employee_name,
     round(case
               when maxsalary<1000 then salary
               when maxsalary<10000 then salary*(1-0.24)
               else salary*(1-0.49)
           end ,0) salary
from
    (select 
          *,
          max(salary) over(partition by company_id ) maxsalary
    from Salaries )t1 ;

95. 周内每天的销售情况

写一个SQL语句,报告 周内每天 每个商品类别下订购了多少单位。返回结果表单 按商品类别排序

查询结果格式如下例所示

+------------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
| Category   | Monday    | Tuesday   | Wednesday | Thursday  | Friday    | Saturday  | Sunday    |
+------------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
| Book       | 20        | 5         | 0         | 0         | 10        | 0         | 0         |
| Glasses    | 0         | 0         | 0         | 0         | 5         | 0         | 0         |
| Phone      | 0         | 0         | 5         | 1         | 0         | 0         | 10        |
| T-Shirt    | 0         | 0         | 0         | 0         | 0         | 0         | 0         |
+------------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
在周一(2020-06-01, 2020-06-08),Book分类(ids: 1, 2)下,总共销售了20个单位(10 + 10)
在周二(2020-06-02),Book分类(ids: 1, 2)下,总共销售了5个单位
在周三(2020-06-03),Phone分类(ids: 3, 4)下,总共销售了5个单位
在周四(2020-06-04),Phone分类(ids: 3, 4)下,总共销售了1个单位
在周五(2020-06-05),Book分类(ids: 1, 2)下,总共销售了10个单位,Glasses分类(ids: 5)下,总共销售了5个单位
在周六, 没有商品销售
在周天(2020-06-14, 2020-06-21),Phone分类(ids: 3, 4)下,总共销售了10个单位(5 + 5)
没有销售 T-Shirt 类别的商品
Create table If Not Exists 95_Orders (order_id int, customer_id int, order_date date, item_id varchar(30), quantity int);
Create table If Not Exists 95_Items (item_id varchar(30), item_name varchar(30), item_category varchar(30));
Truncate table 95_Orders;
insert into 95_Orders (order_id, customer_id, order_date, item_id, quantity) values ('1', '1', '2020-06-01', '1', '10');
insert into 95_Orders (order_id, customer_id, order_date, item_id, quantity) values ('2', '1', '2020-06-08', '2', '10');
insert into 95_Orders (order_id, customer_id, order_date, item_id, quantity) values ('3', '2', '2020-06-02', '1', '5');
insert into 95_Orders (order_id, customer_id, order_date, item_id, quantity) values ('4', '3', '2020-06-03', '3', '5');
insert into 95_Orders (order_id, customer_id, order_date, item_id, quantity) values ('5', '4', '2020-06-04', '4', '1');
insert into 95_Orders (order_id, customer_id, order_date, item_id, quantity) values ('6', '4', '2020-06-05', '5', '5');
insert into 95_Orders (order_id, customer_id, order_date, item_id, quantity) values ('7', '5', '2020-06-05', '1', '10');
insert into 95_Orders (order_id, customer_id, order_date, item_id, quantity) values ('8', '5', '2020-06-14', '4', '5');
insert into 95_Orders (order_id, customer_id, order_date, item_id, quantity) values ('9', '5', '2020-06-21', '3', '5');
Truncate table 95_Items;
insert into 95_Items (item_id, item_name, item_category) values ('1', 'LC Alg. Book', 'Book');
insert into 95_Items (item_id, item_name, item_category) values ('2', 'LC DB. Book', 'Book');
insert into 95_Items (item_id, item_name, item_category) values ('3', 'LC SmarthPhone', 'Phone');
insert into 95_Items (item_id, item_name, item_category) values ('4', 'LC Phone 2020', 'Phone');
insert into 95_Items (item_id, item_name, item_category) values ('5', 'LC SmartGlass', 'Glasses');
insert into 95_Items (item_id, item_name, item_category) values ('6', 'LC T-Shirt XL', 'T-shirt');

最终SQL:

select 
     item_category as category, 
     sum(case when num = 2 then quantity else 0 end) as Monday,
     sum(case when num = 3 then quantity else 0 end) as Tuesday,
     sum(case when num = 4 then quantity else 0 end) as Wednesday,
     sum(case when num = 5 then quantity else 0 end) as Thursday,
     sum(case when num = 6 then quantity else 0 end) as Friday,
     sum(case when num = 7 then quantity else 0 end) as Saturday,
     sum(case when num = 1 then quantity else 0 end) as Sunday
from
    (select
          item_category,
          quantity,
          dayofweek(order_date) as num
     from 
          95_items i
     left join
          95_orders o 
     on 
          i.item_id=o.item_id) t
group by 
     item_category
order by
     item_category;

96. 按日期分组销售产品

编写一个 SQL 查询来查找每个日期、销售的不同产品的数量及其名称。
每个日期的销售产品名称应按词典序排列。
返回按 sell_date 排序的结果表。

查询结果格式如下例所示。

+------------+----------+------------------------------+
| sell_date  | num_sold | products                     |
+------------+----------+------------------------------+
| 2020-05-30 | 3        | Basketball,Headphone,T-shirt |
| 2020-06-01 | 2        | Bible,Pencil                 |
| 2020-06-02 | 1        | Mask                         |
+------------+----------+------------------------------+
对于2020-05-30,出售的物品是 (Headphone, Basketball, T-shirt),按词典序排列,并用逗号 ',' 分隔。
对于2020-06-01,出售的物品是 (Pencil, Bible),按词典序排列,并用逗号分隔。
对于2020-06-02,出售的物品是 (Mask),只需返回该物品名。

建表语句:

Create table If Not Exists 96_Activities (sell_date date, product varchar(20));
Truncate table 96_Activities;
insert into 96_Activities (sell_date, product) values ('2020-05-30', 'Headphone');
insert into 96_Activities (sell_date, product) values ('2020-06-01', 'Pencil');
insert into 96_Activities (sell_date, product) values ('2020-06-02', 'Mask');
insert into 96_Activities (sell_date, product) values ('2020-05-30', 'Basketball');
insert into 96_Activities (sell_date, product) values ('2020-06-01', 'Bible');
insert into 96_Activities (sell_date, product) values ('2020-06-02', 'Mask');
insert into 96_Activities (sell_date, product) values ('2020-05-30', 'T-Shirt');

最终SQL:

select
     sell_date,
     count(distinct product) num_sold, 
     group_concat(distinct product order by product) products
from 
     Activities
group by
     sell_date;

97. 上月播放的儿童适宜电影

写一个 SQL 语句, 报告在 2020 年 6 月份播放的儿童适宜电影的去重电影名.返回的结果表单没有顺序要求.

查询结果的格式如下例所示.

+--------------+
| title        |
+--------------+
| Aladdin      |
+--------------+
"Leetcode Movie" 是儿童不宜的电影.
"Alg. for Kids" 不是电影.
"Database Sols" 不是电影
"Alladin" 是电影, 儿童适宜, 并且在 2020 年 6 月份播放.
"Cinderella" 不在 2020 年 6 月份播放.
Create table If Not Exists 97_TVProgram (program_date date, content_id int, channel varchar(30));
Create table If Not Exists 97_Content (content_id varchar(30), title varchar(30), Kids_content ENUM('Y', 'N'), content_type varchar(30));
Truncate table 97_TVProgram;
insert into 97_TVProgram (program_date, content_id, channel) values ('2020-06-10 08:00', '1', 'LC-Channel');
insert into 97_TVProgram (program_date, content_id, channel) values ('2020-05-11 12:00', '2', 'LC-Channel');
insert into 97_TVProgram (program_date, content_id, channel) values ('2020-05-12 12:00', '3', 'LC-Channel');
insert into 97_TVProgram (program_date, content_id, channel) values ('2020-05-13 14:00', '4', 'Disney Ch');
insert into 97_TVProgram (program_date, content_id, channel) values ('2020-06-18 14:00', '4', 'Disney Ch');
insert into 97_TVProgram (program_date, content_id, channel) values ('2020-07-15 16:00', '5', 'Disney Ch');
Truncate table 97_Content;
insert into 97_Content (content_id, title, Kids_content, content_type) values ('1', 'Leetcode Movie', 'N', 'Movies');
insert into 97_Content (content_id, title, Kids_content, content_type) values ('2', 'Alg. for Kids', 'Y', 'Series');
insert into 97_Content (content_id, title, Kids_content, content_type) values ('3', 'Database Sols', 'N', 'Series');
insert into 97_Content (content_id, title, Kids_content, content_type) values ('4', 'Aladdin', 'Y', 'Movies');
insert into 97_Content (content_id, title, Kids_content, content_type) values ('5', 'Cinderella', 'Y', 'Movies');

最终SQL:

select 
     distinct title   
from 
     97_TVProgram t 
left join
     97_Content c
on 
     t.content_id  = c.content_id 
where
     Kids_content ='Y' 
     and
     date_format(program_date ,'%Y-%m')='2020-06'
     and
     content_type='Movies';

98. 可以放心投资的国家

写一段 SQL, 找到所有该公司可以投资的国家(该国的平均通话时长要严格地大于全球平均通话时长).返回的结果表没有顺序要求.

查询的结果格式如下例所示.

+----------+
| country  |
+----------+
| Peru     |
+----------+
国家Peru的平均通话时长是 (102 + 102 + 330 + 330 + 5 + 5) / 6 = 145.666667
国家Israel的平均通话时长是 (33 + 4 + 13 + 13 + 3 + 1 + 1 + 7) / 8 = 9.37500
国家Morocco的平均通话时长是 (33 + 4 + 59 + 59 + 3 + 7) / 6 = 27.5000 
全球平均通话时长 = (2 * (33 + 3 + 59 + 102 + 330 + 5 + 13 + 3 + 1 + 7)) / 20 = 55.70000
所以, Peru是唯一的平均通话时长大于全球平均通话时长的国家, 也是唯一的推荐投资的国家.
Create table If Not Exists 98_Person (id int, name varchar(15), phone_number varchar(11));
Create table If Not Exists 98_Country (name varchar(15), country_code varchar(3));
Create table If Not Exists 98_Calls (caller_id int, callee_id int, duration int);
Truncate table 98_Person;
insert into 98_Person (id, name, phone_number) values ('3', 'Jonathan', '051-1234567');
insert into 98_Person (id, name, phone_number) values ('12', 'Elvis', '051-7654321');
insert into 98_Person (id, name, phone_number) values ('1', 'Moncef', '212-1234567');
insert into 98_Person (id, name, phone_number) values ('2', 'Maroua', '212-6523651');
insert into 98_Person (id, name, phone_number) values ('7', 'Meir', '972-1234567');
insert into 98_Person (id, name, phone_number) values ('9', 'Rachel', '972-0011100');
Truncate table 98_Country;
insert into 98_Country (name, country_code) values ('Peru', '051');
insert into 98_Country (name, country_code) values ('Israel', '972');
insert into 98_Country (name, country_code) values ('Morocco', '212');
insert into 98_Country (name, country_code) values ('Germany', '049');
insert into 98_Country (name, country_code) values ('Ethiopia', '251');
Truncate table 98_Calls;
insert into 98_Calls (caller_id, callee_id, duration) values ('1', '9', '33');
insert into 98_Calls (caller_id, callee_id, duration) values ('2', '9', '4');
insert into 98_Calls (caller_id, callee_id, duration) values ('1', '2', '59');
insert into 98_Calls (caller_id, callee_id, duration) values ('3', '12', '102');
insert into 98_Calls (caller_id, callee_id, duration) values ('3', '12', '330');
insert into 98_Calls (caller_id, callee_id, duration) values ('12', '3', '5');
insert into 98_Calls (caller_id, callee_id, duration) values ('7', '9', '13');
insert into 98_Calls (caller_id, callee_id, duration) values ('7', '1', '3');
insert into 98_Calls (caller_id, callee_id, duration) values ('9', '7', '1');
insert into 98_Calls (caller_id, callee_id, duration) values ('1', '7', '7');

最终SQL:

-- 方法一
select 
     c2.name as country 
from 
     98_Calls c1,
     98_Person p,
     98_Country c2
where
    (p.id=c1.caller_id or p.id=c1.callee_id) 
     and
     c2.country_code=left(p.phone_number,3)
group by 
     c2.name 
having
     avg(duration)>(select avg(duration) from 98_Calls);

99. 消费者下单频率

写一个 SQL 语句, 报告消费者的 id 和名字, 其中消费者在 2020 年 6 月和 7 月, 每月至少花费了$100.结果表无顺序要求.

查询结果格式如下例所示.

+--------------+------------+
| customer_id  | name       |  
+--------------+------------+
| 1            | Winston    |
+--------------+------------+ 
Winston 在2020年6月花费了$300(300 * 1), 在7月花费了$100(10 * 1 + 45 * 2).
Jonathan 在2020年6月花费了$600(300 * 2), 在7月花费了$20(2 * 10).
Moustafa 在2020年6月花费了$110 (10 * 2 + 45 * 2), 在7月花费了$0.

建表语句:

Create table If Not Exists 99_Customers (customer_id int, name varchar(30), country varchar(30));
Create table If Not Exists 99_Product (product_id int, description varchar(30), price int);
Create table If Not Exists 99_Orders (order_id int, customer_id int, product_id int, order_date date, quantity int);
Truncate table 99_Customers;
insert into 99_Customers (customer_id, name, country) values ('1', 'Winston', 'USA');
insert into 99_Customers (customer_id, name, country) values ('2', 'Jonathan', 'Peru');
insert into 99_Customers (customer_id, name, country) values ('3', 'Moustafa', 'Egypt');
Truncate table 99_Product;
insert into 99_Product (product_id, description, price) values ('10', 'LC Phone', '300');
insert into 99_Product (product_id, description, price) values ('20', 'LC T-Shirt', '10');
insert into 99_Product (product_id, description, price) values ('30', 'LC Book', '45');
insert into 99_Product (product_id, description, price) values ('40', 'LC Keychain', '2');
Truncate table 99_Orders;
insert into 99_Orders (order_id, customer_id, product_id, order_date, quantity) values ('1', '1', '10', '2020-06-10', '1');
insert into 99_Orders (order_id, customer_id, product_id, order_date, quantity) values ('2', '1', '20', '2020-07-01', '1');
insert into 99_Orders (order_id, customer_id, product_id, order_date, quantity) values ('3', '1', '30', '2020-07-08', '2');
insert into 99_Orders (order_id, customer_id, product_id, order_date, quantity) values ('4', '2', '10', '2020-06-15', '2');
insert into 99_Orders (order_id, customer_id, product_id, order_date, quantity) values ('5', '2', '40', '2020-07-01', '10');
insert into 99_Orders (order_id, customer_id, product_id, order_date, quantity) values ('6', '3', '20', '2020-06-24', '2');
insert into 99_Orders (order_id, customer_id, product_id, order_date, quantity) values ('7', '3', '30', '2020-06-25', '2');
insert into 99_Orders (order_id, customer_id, product_id, order_date, quantity) values ('9', '3', '30', '2020-05-08', '3');

最终SQL:

select
     customer_id,name
from 
     Customers
where
     customer_id in (select
                          customer_id
                     from
                         (select 
                                customer_id,
                                month(order_date) as month,
                                sum(quantity*price) as total
                          from 
                                Orders o 
                          left join
                                Product p
                          on 
                                o.product_id = p.product_id
                          where
                                month(order_date) = 6 or month(order_date)=7
                          group by
                                customer_id,month(order_date)
                          ) as t1
                    where 
                          total >=100
                    group by
                          customer_id
                    having
                          count(*)>=2 );

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

Write an SQL query to find the users who have valid emails.

A valid e-mail has a prefix name and a domain where:

  • The prefix name is a string that may contain letters (upper or lower case), digits, underscore '_', period '.' and/or dash '-'. The prefix name must start with a letter.
  • The domain is '@leetcode.com'.

Return the result table in any order.

The query result format is in the following example.

+---------+-----------+-------------------------+
| user_id | name      | mail                    |
+---------+-----------+-------------------------+
| 1       | Winston   | winston@leetcode.com    |
| 3       | Annabelle | bella-@leetcode.com     |
| 4       | Sally     | sally.come@leetcode.com |
+---------+-----------+-------------------------+
The mail of user 2 doesn't have a domain.
The mail of user 5 has # sign which is not allowed.
The mail of user 6 doesn't have leetcode domain.
The mail of user 7 starts with a period.

建表语句:

Create table If Not Exists 100_Users (user_id int, name varchar(30), mail varchar(50));
Truncate table 100_Users;
insert into 100_Users (user_id, name, mail) values ('1', 'Winston', 'winston@leetcode.com');
insert into 100_Users (user_id, name, mail) values ('2', 'Jonathan', 'jonathanisgreat');
insert into 100_Users (user_id, name, mail) values ('3', 'Annabelle', 'bella-@leetcode.com');
insert into 100_Users (user_id, name, mail) values ('4', 'Sally', 'sally.come@leetcode.com');
insert into 100_Users (user_id, name, mail) values ('5', 'Marwan', 'quarz#2020@leetcode.com');
insert into 100_Users (user_id, name, mail) values ('6', 'David', 'david69@gmail.com');
insert into 100_Users (user_id, name, mail) values ('7', 'Shapiro', '.shapo@leetcode.com');

最终SQL:

SELECT
      *
FROM
      100_Users
WHERE 
      mail REGEXP '^[a-zA-Z]+[\\w_\\.\\-]*@leetcode.com$'   
ORDER BY
      user_id;