力扣高频SQL50题(基础版)重点部分

力扣高频SQL50题(基础版)重点部分



每月交易 I

表:Transactions

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| id            | int     |
| country       | varchar |
| state         | enum    |
| amount        | int     |
| trans_date    | date    |
+---------------+---------+
id 是这个表的主键。
该表包含有关传入事务的信息。
state 列类型为 ["approved", "declined"] 之一。

编写一个 sql 查询来查找每个月和每个国家/地区的事务数及其总金额、已批准的事务数及其总金额。

任意顺序 返回结果表。

查询结果格式如下所示。

示例 1:

<strong>输入:</strong>
Transactions table:
+------+---------+----------+--------+------------+
| id   | country | state    | amount | trans_date |
+------+---------+----------+--------+------------+
| 121  | US      | approved | 1000   | 2018-12-18 |
| 122  | US      | declined | 2000   | 2018-12-19 |
| 123  | US      | approved | 2000   | 2019-01-01 |
| 124  | DE      | approved | 2000   | 2019-01-07 |
+------+---------+----------+--------+------------+
<strong>输出:</strong>
+----------+---------+-------------+----------------+--------------------+-----------------------+
| month    | country | trans_count | approved_count | trans_total_amount | approved_total_amount |
+----------+---------+-------------+----------------+--------------------+-----------------------+
| 2018-12  | US      | 2           | 1              | 3000               | 1000                  |
| 2019-01  | US      | 1           | 1              | 2000               | 2000                  |
| 2019-01  | DE      | 1           | 1              | 2000               | 2000                  |
+----------+---------+-------------+----------------+--------------------+-----------------------+
select date_format(trans_date,'%Y-%m') month,country,count(id) trans_count,
count(if(state='approved',1,null)) approved_count,
sum(amount) trans_total_amount,
sum(if(state='approved',amount,0)) approved_total_amount 
from Transactions 
group by month,country;

select date_format(trans_date,'%Y-%m') month,country,count(id) trans_count,
ifnull(count(case when state='approved' then id end),0) approved_count,
sum(amount) trans_total_amount,
ifnull(sum(case when state='approved' then amount end),0) approved_total_amount 
from Transactions 
group by month,country;

# 一种是先处理再进行聚合,一种是先聚合统计再处理空值问题
# 注意使用合适的日期函数,还有空值的处理
游戏玩法分析 IV

Table: Activity

+--------------+---------+
| Column Name  | Type    |
+--------------+---------+
| player_id    | int     |
| device_id    | int     |
| event_date   | date    |
| games_played | int     |
+--------------+---------+
(player_id,event_date)是此表的主键(具有唯一值的列的组合)。
这张表显示了某些游戏的玩家的活动情况。
每一行是一个玩家的记录,他在某一天使用某个设备注销之前登录并玩了很多游戏(可能是 0)。

编写解决方案,报告在首次登录的第二天再次登录的玩家的 比率四舍五入到小数点后两位。换句话说,你需要计算从首次登录日期开始至少连续两天登录的玩家的数量,然后除以玩家总数。

结果格式如下所示:

示例 1:

<strong>输入:</strong>
Activity table:
+-----------+-----------+------------+--------------+
| player_id | device_id | event_date | games_played |
+-----------+-----------+------------+--------------+
| 1         | 2         | 2016-03-01 | 5            |
| 1         | 2         | 2016-03-02 | 6            |
| 2         | 3         | 2017-06-25 | 1            |
| 3         | 1         | 2016-03-02 | 0            |
| 3         | 4         | 2018-07-03 | 5            |
+-----------+-----------+------------+--------------+
<strong>输出:</strong>
+-----------+
| fraction  |
+-----------+
| 0.33      |
+-----------+
<strong>解释:</strong>
只有 ID 为 1 的玩家在第一天登录后才重新登录,所以答案是 1/3 = 0.33
# 答案
 
# 连续登录问题 1 定义法 根据用户登录日期排序,取上一行登录日期,和本行的登录日期差为1,即为连续2天登录
select round(count(case when lag_value2 =-1 and datediff(event_date,lag_value1)=1 then player_id end)/count(distinct player_id),2) fraction
from (select player_id,device_id,event_date,
lag(event_date,1,-1) over(partition by player_id order by event_date) lag_value1, 
lag(event_date,2,-1) over(partition by player_id order by event_date) lag_value2  
from Activity) a ;

# 注意是首次登录,注意这个条件,有的用户可能是首次登录之后,第二天没有登录,但是后面又发生了连续登录两天,这种情况就不符合题意
# 所以要限制lag_value2=-1这个条件,另外lag_value2=-1 and datediff(event_date,lag_value1)=1 限制了
# 首次登录的第二天登录的那条记录,每个用户只有一条数据,不用剔重,不用count(distinct case when lag_value2=-1...)

# 关联join
# 先筛选出每个用户的首次登录时间,根据用户id和登录时间差为1条件进行关联,筛选出不为null的数据


select round(count(case when b.event_date is not null then a.player_id end)/count(a.player_id),2) fraction
from (select player_id,min(event_date) min_date 
from Activity group by player_id) a 
left join Activity b on a.player_id=b.player_id and datediff(b.event_date,a.min_date)=1;

# 后续补充
select round(count(distinct case when z.rn=1 and date_diff=-1 then player_id end)/count(distinct player_id),2) fraction 
from (select a.*,row_number() over(partition by player_id order by event_date) rn,
datediff(event_date,lead(event_date,1,0) over(partition by player_id order by event_date)) date_diff
from activity a) z
销售分析 III

表: Product

+--------------+---------+
| Column Name  | Type    |
+--------------+---------+
| product_id   | int     |
| product_name | varchar |
| unit_price   | int     |
+--------------+---------+
product_id 是该表的主键(具有唯一值的列)。
该表的每一行显示每个产品的名称和价格。

表:Sales

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| seller_id   | int     |
| product_id  | int     |
| buyer_id    | int     |
| sale_date   | date    |
| quantity    | int     |
| price       | int     |
+------ ------+---------+
这个表可能有重复的行。
product_id 是 Product 表的外键(reference 列)。
该表的每一行包含关于一个销售的一些信息。

编写解决方案,报告 2019年春季 才售出的产品。即2019-01-012019-03-31(含)之间出售的商品。

任意顺序 返回结果表。

结果格式如下所示。

示例 1:

<strong>输入:</strong>
Product table:
+------------+--------------+------------+
| product_id | product_name | unit_price |
+------------+--------------+------------+
| 1          | S8           | 1000       |
| 2          | G4           | 800        |
| 3          | iPhone       | 1400       |
+------------+--------------+------------+
Sales table:
+-----------+------------+----------+------------+----------+-------+
| seller_id | product_id | buyer_id | sale_date  | quantity | price |
+-----------+------------+----------+------------+----------+-------+
| 1         | 1          | 1        | 2019-01-21 | 2        | 2000  |
| 1         | 2          | 2        | 2019-02-17 | 1        | 800   |
| 2         | 2          | 3        | 2019-06-02 | 1        | 800   |
| 3         | 3          | 4        | 2019-05-13 | 2        | 2800  |
+-----------+------------+----------+------------+----------+-------+
<strong>输出:</strong>
+-------------+--------------+
| product_id  | product_name |
+-------------+--------------+
| 1           | S8           |
+-------------+--------------+
<strong>解释:</strong>
id为1的产品仅在2019年春季销售。
id为2的产品在2019年春季销售,但也在2019年春季之后销售。
id 3的产品在2019年春季之后销售。
我们只退回产品1,因为它是2019年春季才销售的产品。
# 答案
select a.product_id,a.product_name 
from Product a 
inner join Sales b on a.product_id=b.product_id 
group by a.product_id,a.product_name 
having max(sale_date) <= '2019-03-31' and min(sale_date) >='2019-01-01';

select product_id,product_name 
from Product 
where product_id not in (select a.product_id
from Sales a where sale_date > '2019-03-31' or sale_date <'2019-01-01') 
and product_id in (select z.product_id from Sales z) ;  

# 注意才出售,意思是只有在春季出售,其他时间不出售
连续出现的数字

表:Logs

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| id          | int     |
| num         | varchar |
+-------------+---------+SQL 中,id 是该表的主键。
id 是一个自增列。

找出所有至少连续出现三次的数字。

返回的结果表中的数据可以按 任意顺序 排列。

结果格式如下面的例子所示:

示例 1:

<strong>输入:</strong>
Logs 表:
+----+-----+
| id | num |
+----+-----+
| 1  | 1   |
| 2  | 1   |
| 3  | 1   |
| 4  | 2   |
| 5  | 1   |
| 6  | 2   |
| 7  | 2   |
+----+-----+
<strong>输出:</strong>
Result 表:
+-----------------+
| ConsecutiveNums |
+-----------------+
| 1               |
+-----------------+
<strong>解释:</strong>1 是唯一连续出现至少三次的数字。
# 答案
select num ConsecutiveNums
from (select num,(cast(rn as signed)-id) num_sub 
from (select id,num,row_number() over(partition by num order by id) rn
from Logs ) a 
group by num,num_sub  
having count(1)>=3) b 
group by num;


# 定义法
select num ConsecutiveNums 
from (select id,num,
lag(num,1,-1) over(order by id) lag_value1, 
lag(num,2,-1) over(order by id) lag_value2  
from Logs) a 
where lag_value1=num and lag_value2=num 
group by num;
指定日期的产品价格

产品数据表: Products

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| product_id    | int     |
| new_price     | int     |
| change_date   | date    |
+---------------+---------+
这张表的主键是 (product_id, change_date)。
这张表的每一行分别记录了 某产品 在某个日期 更改后 的新价格。

写一段 SQL 来查找在 2019-08-16 时全部产品的价格,假设所有产品在修改前的价格都是 10

任意顺序 返回结果表。

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

示例 1:

<strong>输入:</strong>
Products 表:
+------------+-----------+-------------+
| product_id | new_price | change_date |
+------------+-----------+-------------+
| 1          | 20        | 2019-08-14  |
| 2          | 50        | 2019-08-14  |
| 1          | 30        | 2019-08-15  |
| 1          | 35        | 2019-08-16  |
| 2          | 65        | 2019-08-17  |
| 3          | 20        | 2019-08-18  |
+------------+-----------+-------------+
<strong>输出:</strong>
+------------+-------+
| product_id | price |
+------------+-------+
| 2          | 50    |
| 1          | 35    |
| 3          | 10    |
+------------+-------+
# 答案
# 引入辅助列,设置为小于2019-08-16日期的,再进行排名,取小于2019-08-16范围内最大的记录的数据,如果没有则为10
select product_id,if(date_new=0,10,new_price) price 
from (select z.*,row_number() over(partition by product_id order by date_new desc) rn 
from (select a.*,case when change_date <= '2019-08-16' then change_date else 0 end date_new from Products a) z ) zz 
where rn=1;
按分类统计薪水

表: Accounts

+-------------+------+
| 列名        | 类型  |
+-------------+------+
| account_id  | int  |
| income      | int  |
+-------------+------+SQL 中,account_id 是这个表的主键。
每一行都包含一个银行帐户的月收入的信息。

查询每个工资类别的银行账户数量。 工资类别如下:

  • "Low Salary":所有工资 严格低于 20000 美元。
  • "Average Salary"包含 范围内的所有工资 [$20000, $50000]
  • "High Salary":所有工资 严格大于 50000 美元。

结果表 必须 包含所有三个类别。 如果某个类别中没有帐户,则报告 0

任意顺序 返回结果表。

查询结果格式如下示例。

示例 1:

<strong>输入:</strong>
Accounts 表:
+------------+--------+
| account_id | income |
+------------+--------+
| 3          | 108939 |
| 2          | 12747  |
| 8          | 87709  |
| 6          | 91796  |
+------------+--------+
<strong>输出:</strong>
+----------------+----------------+
| category       | accounts_count |
+----------------+----------------+
| Low Salary     | 1              |
| Average Salary | 0              |
| High Salary    | 3              |
+----------------+----------------+
<strong>解释:</strong>
低薪: 有一个账户 2.
中等薪水: 没有.
高薪: 有三个账户,他们是 3, 68.
# 答案

select 'Low Salary' as category,sum(if(income <20000,1,0)) accounts_count from Accounts
union all 
select 'Average Salary' as category,sum(if(income between 20000 and 50000,1,0)) accounts_count from Accounts
union all 
select 'High Salary' as category,sum(if(income >50000,1,0)) accounts_count from Accounts;

# 两种思路:1.造出来这三个类别,和表进行关联 2. union all
换座位

表: Seat

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| id          | int     |
| name        | varchar |
+-------------+---------+
id 是该表的主键(唯一值)列。
该表的每一行都表示学生的姓名和 ID。
id 是一个连续的增量。

编写解决方案来交换每两个连续的学生的座位号。如果学生的数量是奇数,则最后一个学生的 id 不交换。

id 升序 返回结果表。

查询结果格式如下所示。

示例 1:

<strong>输入:</strong> 
Seat 表:
+----+---------+
| id | student |
+----+---------+
| 1  | Abbot   |
| 2  | Doris   |
| 3  | Emerson |
| 4  | Green   |
| 5  | Jeames  |
+----+---------+
<strong>输出:</strong> 
+----+---------+
| id | student |
+----+---------+
| 1  | Doris   |
| 2  | Abbot   |
| 3  | Green   |
| 4  | Emerson |
| 5  | Jeames  |
+----+---------+
<strong>解释:
</strong>请注意,如果学生人数为奇数,则不需要更换最后一名学生的座位。
# 答案

# 奇数+1,偶数-1,最大id为奇数则不变
select id,student 
from (select id-1 id,student from Seat where mod(id,2)=0 
union 
select id+1 id,student from Seat where mod(id,2)=1 and id not in (select max(id) from Seat) 
union  
select if(mod(id,2)=1,id,id-1) id,student from Seat where id in (select max(id) from Seat)) z order by id; 


# lag,lead需要考虑总数据量,注意点是lead(id,1,id)
select id,student 
from (select if(mod(id,2)=0,lag(id,1) over(order by id),lead(id,1,id) over(order by id)) id,student from Seat  
union  
select if(mod(id,2)=0,id-1,id) id,student from Seat where id in (select max(id) from Seat)) z order by id;
# 开窗函数的运用

select id,student 
from (select case when mod(id,2)=1 and counts <> id then id+1 
when mod(id,2)=1 and counts = id then id 
when mod(id,2)<>1 then id-1 end id,student  
from Seat,(select max(id) counts from Seat) seat_counts) z 
order by id ;
# 注意这种写法
电影评分

表:Movies

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| movie_id      | int     |
| title         | varchar |
+---------------+---------+
movie_id 是这个表的主键(具有唯一值的列)。
title 是电影的名字。

表:Users

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| user_id       | int     |
| name          | varchar |
+---------------+---------+
user_id 是表的主键(具有唯一值的列)

表:MovieRating

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| movie_id      | int     |
| user_id       | int     |
| rating        | int     |
| created_at    | date    |
+---------------+---------+
(movie_id, user_id) 是这个表的主键(具有唯一值的列的组合)。
这个表包含用户在其评论中对电影的评分 rating 。
created_at 是用户的点评日期。

请你编写一个解决方案:

  • 查找评论电影数量最多的用户名。如果出现平局,返回字典序较小的用户名。
  • 查找在 February 2020 平均评分最高 的电影名称。如果出现平局,返回字典序较小的电影名称。

字典序 ,即按字母在字典中出现顺序对字符串排序,字典序较小则意味着排序靠前。

返回结果格式如下例所示。

示例 1:

<strong>输入:</strong>
Movies 表:
+-------------+--------------+
| movie_id    |  title       |
+-------------+--------------+
| 1           | Avengers     |
| 2           | Frozen 2     |
| 3           | Joker        |
+-------------+--------------+
Users 表:
+-------------+--------------+
| user_id     |  name        |
+-------------+--------------+
| 1           | Daniel       |
| 2           | Monica       |
| 3           | Maria        |
| 4           | James        |
+-------------+--------------+
MovieRating 表:
+-------------+--------------+--------------+-------------+
| movie_id    | user_id      | rating       | created_at  |
+-------------+--------------+--------------+-------------+
| 1           | 1            | 3            | 2020-01-12  |
| 1           | 2            | 4            | 2020-02-11  |
| 1           | 3            | 2            | 2020-02-12  |
| 1           | 4            | 1            | 2020-01-01  |
| 2           | 1            | 5            | 2020-02-17  | 
| 2           | 2            | 2            | 2020-02-01  | 
| 2           | 3            | 2            | 2020-03-01  |
| 3           | 1            | 3            | 2020-02-22  | 
| 3           | 2            | 4            | 2020-02-25  | 
+-------------+--------------+--------------+-------------+
<strong>输出:</strong>
Result 表:
+--------------+
| results      |
+--------------+
| Daniel       |
| Frozen 2     |
+--------------+
<strong>解释:</strong>
Daniel 和 Monica 都点评了 3 部电影("Avengers", "Frozen 2""Joker") 但是 Daniel 字典序比较小。
Frozen 2 和 Joker 在 2 月的评分都是 3.5,但是 Frozen 2 的字典序比较小。
# 答案

(select name results
from (select user_id,count(distinct movie_id) cnt 
from MovieRating group by user_id) a inner join Users b on a.user_id=b.user_id 
order by cnt desc,b.name asc limit 1) 
union all 
(select b.title 
from (select movie_id,avg(rating) avg_score 
from MovieRating where substr(created_at,1,7)='2020-02' group by movie_id) a inner join Movies b on a.movie_id=b.movie_id 
order by avg_score desc,b.title asc limit 1);
餐馆营业额变化增长

表: Customer

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| customer_id   | int     |
| name          | varchar |
| visited_on    | date    |
| amount        | int     |
+---------------+---------+SQL 中,(customer_id, visited_on) 是该表的主键。
该表包含一家餐馆的顾客交易数据。
visited_on 表示 (customer_id) 的顾客在 visited_on 那天访问了餐馆。
amount 是一个顾客某一天的消费总额。

你是餐馆的老板,现在你想分析一下可能的营业额变化增长(每天至少有一位顾客)。

计算以 7 天(某日期 + 该日期前的 6 天)为一个时间段的顾客消费平均值。average_amount保留两位小数。

结果按 visited_on 升序排序

返回结果格式的例子如下。

示例 1:

<strong>输入:</strong>
Customer 表:
+-------------+--------------+--------------+-------------+
| customer_id | name         | visited_on   | amount      |
+-------------+--------------+--------------+-------------+
| 1           | Jhon         | 2019-01-01   | 100         |
| 2           | Daniel       | 2019-01-02   | 110         |
| 3           | Jade         | 2019-01-03   | 120         |
| 4           | Khaled       | 2019-01-04   | 130         |
| 5           | Winston      | 2019-01-05   | 110         | 
| 6           | Elvis        | 2019-01-06   | 140         | 
| 7           | Anna         | 2019-01-07   | 150         |
| 8           | Maria        | 2019-01-08   | 80          |
| 9           | Jaze         | 2019-01-09   | 110         | 
| 1           | Jhon         | 2019-01-10   | 130         | 
| 3           | Jade         | 2019-01-10   | 150         | 
+-------------+--------------+--------------+-------------+
<strong>输出:</strong>
+--------------+--------------+----------------+
| visited_on   | amount       | average_amount |
+--------------+--------------+----------------+
| 2019-01-07   | 860          | 122.86         |
| 2019-01-08   | 840          | 120            |
| 2019-01-09   | 840          | 120            |
| 2019-01-10   | 1000         | 142.86         |
+--------------+--------------+----------------+
<strong>解释:</strong>
第一个七天消费平均值从 2019-01-012019-01-07 是restaurant-growth/restaurant-growth/ (100 + 110 + 120 + 130 + 110 + 140 + 150)/7 = 122.86
第二个七天消费平均值从 2019-01-022019-01-08(110 + 120 + 130 + 110 + 140 + 150 + 80)/7 = 120
第三个七天消费平均值从 2019-01-032019-01-09(120 + 130 + 110 + 140 + 150 + 80 + 110)/7 = 120
第四个七天消费平均值从 2019-01-042019-01-10(130 + 110 + 140 + 150 + 80 + 110 + 130 + 150)/7 = 142.86
select visited_on,sum_row amount,round(sum_row/7,2) average_amount 
from (select a.*,sum(amount) over(order by visited_on range between interval 6 day preceding and current row) sum_row
from (select visited_on,sum(amount) amount from Customer group by visited_on) a ) z 
where date_sub(visited_on,interval 6 day)>=(select min(visited_on) from Customer)
order by visited_on;

# 这里使用range滑动窗口


select visited_on,sum_amt amount,round(sum_amt/7,2) average_amount 
from (select a.visited_on,sum(b.amount) sum_amt  
from (select distinct visited_on from Customer) a 
left join Customer b on b.visited_on between date_sub(a.visited_on,interval 6 day) and a.visited_on 
group by a.visited_on) z  
having date_sub(visited_on,interval 6 day) >=(select min(visited_on) from Customer)
order by visited_on ;
# 注意a表要进行剔重,要不然(一天中有多条数据的情况下)与b表关联会多算,多一条,算一倍
按日期分组销售产品

Activities

+-------------+---------+
| 列名         | 类型    |
+-------------+---------+
| sell_date   | date    |
| product     | varchar |
+-------------+---------+
该表没有主键(具有唯一值的列)。它可能包含重复项。
此表的每一行都包含产品名称和在市场上销售的日期。

编写解决方案找出每个日期、销售的不同产品的数量及其名称。
每个日期的销售产品名称应按词典序排列。
返回按 sell_date 排序的结果表。
结果表结果格式如下例所示。

示例 1:

<strong>输入:</strong>
Activities 表:
+------------+-------------+
| sell_date  | product     |
+------------+-------------+
| 2020-05-30 | Headphone   |
| 2020-06-01 | Pencil      |
| 2020-06-02 | Mask        |
| 2020-05-30 | Basketball  |
| 2020-06-01 | Bible       |
| 2020-06-02 | Mask        |
| 2020-05-30 | T-Shirt     |
+------------+-------------+
<strong>输出:</strong>
+------------+----------+------------------------------+
| sell_date  | num_sold | products                     |
+------------+----------+------------------------------+
| 2020-05-30 | 3        | Basketball,Headphone,T-shirt |
| 2020-06-01 | 2        | Bible,Pencil                 |
| 2020-06-02 | 1        | Mask                         |
+------------+----------+------------------------------+
<strong>解释:</strong>
对于2020-05-30,出售的物品是 (Headphone, Basketball, T-shirt),按词典序排列,并用逗号 ',' 分隔。
对于2020-06-01,出售的物品是 (Pencil, Bible),按词典序排列,并用逗号分隔。
对于2020-06-02,出售的物品是 (Mask),只需返回该物品名。
# 答案

# 难点在行转列
select sell_date,count(distinct product) num_sold,group_concat(distinct product separator ',') products 
from Activities 
group by sell_date 
order by sell_date;
查找拥有有效邮箱的用户

表: Users

+---------------+---------+
| Column Name   | Type    |
+---------------+---------+
| user_id       | int     |
| name          | varchar |
| mail          | varchar |
+---------------+---------+
user_id 是该表的主键(具有唯一值的列)。
该表包含了网站已注册用户的信息。有一些电子邮件是无效的。

编写一个解决方案,以查找具有有效电子邮件的用户。

一个有效的电子邮件具有前缀名称和域,其中:

  1. 前缀 名称是一个字符串,可以包含字母(大写或小写),数字,下划线 '_' ,点 '.' 和/或破折号 '-' 。前缀名称 必须 以字母开头。
  2. '``@leetcode.com``'

以任何顺序返回结果表。

结果的格式如以下示例所示:

示例 1:

<strong>输入:</strong>
Users 表:
+---------+-----------+-------------------------+
| user_id | name      | mail                    |
+---------+-----------+-------------------------+
| 1       | Winston   | winston@leetcode.com    |
| 2       | Jonathan  | jonathanisgreat         |
| 3       | Annabelle | bella-@leetcode.com     |
| 4       | Sally     | sally.come@leetcode.com |
| 5       | Marwan    | quarz#2020@leetcode.com |
| 6       | David     | david69@gmail.com       |
| 7       | Shapiro   | .shapo@leetcode.com     |
+---------+-----------+-------------------------+
<strong>输出:</strong>
+---------+-----------+-------------------------+
| user_id | name      | mail                    |
+---------+-----------+-------------------------+
| 1       | Winston   | winston@leetcode.com    |
| 3       | Annabelle | bella-@leetcode.com     |
| 4       | Sally     | sally.come@leetcode.com |
+---------+-----------+-------------------------+
<strong>解释:</strong>
用户 2 的电子邮件没有域。 
用户 5 的电子邮件带有不允许的 '#' 符号。
用户 6 的电子邮件没有 leetcode 域。 
用户 7 的电子邮件以点开头。
# 答案

select user_id, name, mail 
from Users 
where mail regexp '^[a-zA-Z][a-zA-Z0-9_.-]*\\@leetcode\\.com$';


思路
一般来说,如果你被要求匹配一个字符串,应该最先想到写一个正则表达式模式进行匹配。

正则表达式提供各种功能,以下是一些相关功能:

^:表示一个字符串或行的开头

[a-z]:表示一个字符范围,匹配从 a 到 z 的任何字符。

[0-9]:表示一个字符范围,匹配从 09 的任何字符。

[a-zA-Z]:这个变量匹配从 a 到 z 或 A 到 Z 的任何字符。请注意,你可以在方括号内指定的字符范围的数量没有限制,您可以添加想要匹配的其他字符或范围。

[^a-z]:这个变量匹配不在 a 到 z 范围内的任何字符。请注意,字符 ^ 用来否定字符范围,它在方括号内的含义与它的方括号外表示开始的含义不同。

[a-z]*:表示一个字符范围,匹配从 a 到 z 的任何字符 0 次或多次。

[a-z]+:表示一个字符范围,匹配从 a 到 z 的任何字符 1 次或多次。

.:匹配任意一个字符。

\.:表示句点字符。请注意,反斜杠用于转义句点字符,因为句点字符在正则表达式中具有特殊含义。还要注意,在许多语言中,你需要转义反斜杠本身,因此需要使用\\.。

$:表示一个字符串或行的结尾。

核心思想是将 name 列的第一个字符从其余字符分开,相应地改变它们的大小写,最后把他们拼回在一起。

  • 19
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值