LeetCode mysql 刷题一:计算特殊奖金 | 买下所有产品的客户

实际开发中 sql 的高级用法并不常用,特别是在做数据库迁移时,高级用法简直是噩梦

只满足于简单的查询,然后用代码实现相关逻辑,又感觉自己的 sql 能力太弱

通过 leetcode 中数据库相关的练习题,刷下题目,增加下自己的 sql 能力

leetcode 只提供了 MySQLOracle 两种数据库,我是用 MySQL 刷题的

下面两条题目:

  • 第一题[简单],主要考察 MySQL 的基本用法:比如正则使用,条件判断,如果判断偶数
  • 第二题[中等],主要考察 MySQL 的高级用法:比如将一张表的统计结果去和另一张表的数据做匹配

题目一

题目链接:计算特殊奖金

编写解决方案,计算每个雇员的奖金。如果一个雇员的 id 是 奇数 并且他的名字不是以 'M' 开头,那么他的奖金是他工资的 100% ,否则奖金为 0 。

返回的结果按照 employee_id 排序。

sql 复制代码
Create table If Not Exists Employees (employee_id int, name varchar(30), salary int);
Truncate table Employees;
insert into Employees (employee_id, name, salary) values ('2', 'Meir', '3000');
insert into Employees (employee_id, name, salary) values ('3', 'Michael', '3800');
insert into Employees (employee_id, name, salary) values ('7', 'Addilyn', '7400');
insert into Employees (employee_id, name, salary) values ('8', 'Juan', '6100');
insert into Employees (employee_id, name, salary) values ('9', 'Kannon', '7700');
lua 复制代码
输入:
Employees 表:
+-------------+---------+--------+
| employee_id | name    | salary |
+-------------+---------+--------+
| 2           | Meir    | 3000   |
| 3           | Michael | 3800   |
| 7           | Addilyn | 7400   |
| 8           | Juan    | 6100   |
| 9           | Kannon  | 7700   |
+-------------+---------+--------+
输出:
+-------------+-------+
| employee_id | bonus |
+-------------+-------+
| 2           | 0     |
| 3           | 0     |
| 7           | 7400  |
| 8           | 0     |
| 9           | 7700  |
+-------------+-------+
解释:
因为雇员id是偶数,所以雇员id 是2和8的两个雇员得到的奖金是0。
雇员id为3的因为他的名字以'M'开头,所以,奖金是0。
其他的雇员得到了百分之百的奖金。

解析

本题考察了三个知识点:

  1. 判断 name 中首字母是 M 的方法有 LIKEREGEXP 两种:
    • 使用 LIKE,用左匹配:M%
    • 使用 REGEXP,正则匹配有很多种,正则的写法有很多种,就不一一列举了
      • ^M:以 M 开头
      • ^M.*:以 M 开头,后面跟任意字符
      • ^[^M]:以非 M 开头
    • 还有一个跟 REGEXP 类似的 RLIKE,也是匹配正则
  2. 匹配偶数方法有很多,可以看这题 620. 有趣的电影,用了 6 种方法判断奇数
  3. 条件判断如果满足输出 bonus 否者输出 0,有两种方法:
    • IFIF (condition, true, false)
    • CASECASE WHEN condition THEN true ELSE false END

掌握了上面的方法,你就可以写出 24SQL 语句了,下面是其中一种

sql 复制代码
SELECT
	employee_id,
	IF (employee_id % 2 != 0 AND name NOT LIKE 'M%', salary, 0) bonus
FROM
	Employees
ORDER BY employee_id;

题目二

题目链接:买下所有产品的客户

编写解决方案,报告 Customer 表中购买了 Product 表中所有产品的客户的 id。

返回结果表 无顺序要求。

返回结果格式如下所示。

sql 复制代码
Create table If Not Exists Customer (customer_id int, product_key int);
Create table Product (product_key int);
Truncate table Customer;
insert into Customer (customer_id, product_key) values ('1', '5');
insert into Customer (customer_id, product_key) values ('2', '6');
insert into Customer (customer_id, product_key) values ('3', '5');
insert into Customer (customer_id, product_key) values ('3', '6');
insert into Customer (customer_id, product_key) values ('1', '6');
Truncate table Product;
insert into Product (product_key) values ('5');
insert into Product (product_key) values ('6');
sql 复制代码
Customer 表:
+-------------+-------------+
| customer_id | product_key |
+-------------+-------------+
| 1           | 5           |
| 2           | 6           |
| 3           | 5           |
| 3           | 6           |
| 1           | 6           |
+-------------+-------------+
该表可能包含重复的行。
customer_id 不为 NULL。
product_key 是 Product 表的外键(reference 列)。

Product 表:
+-------------+
| product_key |
+-------------+
| 5           |
| 6           |
+-------------+
输出:
+-------------+
| customer_id |
+-------------+
| 1           |
| 3           |
+-------------+
product_key 是这张表的主键(具有唯一值的列)。

解释:
购买了所有产品(5 和 6)的客户的 id 是 1 和 3 。

本题考察了 2 个知识点:

  1. 如何查询出一个用户购买了多少件商品
  2. 如何关联两张表中的数据

解析

方法一

  1. 全部有多少件商品:

    • SELECT COUNT(*) FROM product;
  2. 每个用户购买了哪些商品:

    • SELECT customer_id, group_concat(product_key) AS product_key FROM Customer GROUP BY customer_id;
  3. 分组之后通过 having 过滤掉购买商品数量不等于全部商品数量的用户:

    • 第一个 count 需要使用 distinct 去重,可能会出现同一个用户买了多件商品
    • 第二个 count 不需要去重,因为商品不会重复 COUNT(DISTINCT product_key) = (SELECT COUNT(*) FROM Product);
sql 复制代码
SELECT
  customer_id
FROM
  Customer
GROUP BY
  customer_id
HAVING
  count( DISTINCT product_key ) = ( SELECT count(*) FROM Product );

方法二

  1. 先通过 group by coustomer_id 分组

  2. 分组之后,可以使用 group_concat 函数将商品编号拼接成字符串

    • group_concat( DISTINCT product_key ORDER BY product_key ):将 Customer 表中每个用户购买的商品编号拼接成字符串
    • SELECT group_concat( product_key ORDER BY product_key ) FROM Product:将 Product 表中的商品编号拼接成字符串
  3. 然后比较两个字符串是否相等

sql 复制代码
SELECT
  customer_id
FROM
  Customer
GROUP BY
  customer_id
HAVING
  group_concat( DISTINCT product_key ORDER BY product_key ) = ( SELECT group_concat( product_key ORDER BY product_key ) FROM Product )

更多题目

leetcode 刷题

相关推荐
linsa_pursuer10 分钟前
快乐数算法
算法·leetcode·职场和发展
XuanRanDev15 分钟前
【每日一题】LeetCode - 三数之和
数据结构·算法·leetcode·1024程序员节
代码猪猪傻瓜coding17 分钟前
力扣1 两数之和
数据结构·算法·leetcode
时差9531 小时前
【面试题】Hive 查询:如何查找用户连续三天登录的记录
大数据·数据库·hive·sql·面试·database
让学习成为一种生活方式1 小时前
R包下载太慢安装中止的解决策略-R语言003
java·数据库·r语言
秋意钟2 小时前
MySQL日期类型选择建议
数据库·mysql
南宫生2 小时前
贪心算法习题其三【力扣】【算法学习day.20】
java·数据结构·学习·算法·leetcode·贪心算法
Dxy12393102162 小时前
python下载pdf
数据库·python·pdf
ac-er88882 小时前
MySQL如何实现PHP输入安全
mysql·安全·php
桀桀桀桀桀桀3 小时前
数据库中的用户管理和权限管理
数据库·mysql