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 刷题

相关推荐
贝多芬也爱敲代码10 分钟前
如何减小ES和mysql的同步时间差
大数据·mysql·elasticsearch
安当加密1 小时前
MySQL数据库透明加密(TDE)解决方案:基于国密SM4的合规与性能优化实践
数据库·mysql·性能优化
007php0071 小时前
某大厂跳动面试:计算机网络相关问题解析与总结
java·开发语言·学习·计算机网络·mysql·面试·职场和发展
JH30731 小时前
第七篇:Buffer Pool 与 InnoDB 其他组件的协作
java·数据库·mysql·oracle
板凳坐着晒太阳2 小时前
ClickHouse 配置优化与问题解决
数据库·clickhouse
数据库生产实战2 小时前
解析Oracle 19C中并行INSERT SELECT的工作原理
数据库·oracle
AAA修煤气灶刘哥3 小时前
服务器指标多到“洪水泛滥”?试试InfluxDB?
数据库·后端·面试
阿沁QWQ3 小时前
MySQL服务器配置与管理
服务器·数据库·mysql
zycoder.4 小时前
力扣面试经典150题day1第一题(lc88),第二题(lc27)
算法·leetcode·面试
Dream it possible!4 小时前
LeetCode 面试经典 150_哈希表_存在重复元素 II(46_219_C++_简单)
leetcode·面试·散列表