当前位置: 首页 > backend >正文

【LeetCode】高频 SQL 50题 题解

目录

查询

可回收且低脂的产品

寻找用户推荐人

大的国家

文章浏览 I

无效的推文

连接

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

产品销售分析 I

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

上升的温度

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

员工奖金

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

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

确认率

聚合函数

有趣的电影

平均售价

项目员工 I

各赛事的用户注册率

查询结果的质量和占比

每月交易 I

即时食物配送 II

游戏玩法分析 IV

排序和分组

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

查询近30天活跃用户数

销售分析 III

超过5名学生的课

求关注者的数量

只出现一次的最大数字

买下所有产品的客户

高级查询和连接

每位经理的下属员工数量

员工的直属部门

判断三角形

连续出现的数字

指定日期的产品价格

最后一个能进入巴士的人

按分类统计薪水

子查询

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

换座位

电影评分

餐馆营业额变化增长

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

2016年的投资

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

高级字符串函数

修复表中的名字

患某种疾病的患者

按日期分组销售产品

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

正则表达式 

查找拥有有效邮箱的用户

子句

删除重复的电子邮箱

第二高的薪水


查询

可回收且低脂的产品

1757. 可回收且低脂的产品 - 力扣(LeetCode)

简单查询

select product_id 
from products 
where low_fats='Y'and recyclable='Y';

寻找用户推荐人

584. 寻找用户推荐人 - 力扣(LeetCode)

注意和null值比较需要用is null和is not null

select name 
from customer 
where referee_id !=2 or referee_id is null;

大的国家

595. 大的国家 - 力扣(LeetCode)

简单查询

select name,population,area 
from world 
where area>=3e6or population>=25e6;

文章浏览 I

1148. 文章浏览 I - 力扣(LeetCode)

distinct消除重复,order 默认升序

selectdistinct author_id as id
fromviews
whereauthor_id=viewer_id
order byid;

无效的推文

1683. 无效的推文 - 力扣(LeetCode)

char_length返回字符数,length返回字节数

selecttweet_id
fromtweets
wherechar_length(content)>15;

连接

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

1378. 使用唯一标识码替换员工ID - 力扣(LeetCode)

左外连接,左表全数据

selectunique_id,name
fromemployees e left join employeeUNI i
one.id=i.id;

using当两个表使用相同名称的列进行连接时

selectunique_id,name
fromemployees  left join employeeUNI using(id);

产品销售分析 I

1068. 产品销售分析 I - 力扣(LeetCode)

左连接

select product_name,year,price
fromsales left join product using(product_id);

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

1581. 进店却未进行过交易的顾客 - 力扣(LeetCode)

左连接,没有交易就是对应交易id为null,按用户id分组统计次数

selectcustomer_id, count(visit_id)as count_no_trans
from visits left join transactions using(visit_id)
wheretransaction_id is null
group bycustomer_id;

上升的温度

197. 上升的温度 - 力扣(LeetCode)

自连接,匹配条件是日期相差一天,筛温度更高的

select w1.id
fromweather w1 join weather w2
ondatediff(w1.recordDate,w2.recordDate)=1
wherew1.temperature>w2.temperature;

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

1661. 每台机器的进程平均运行时间 - 力扣(LeetCode)

为什么这几道题都没有官方解答

小数格式用round,用if取值,如果是开始就减去,如果是结束就加上

selectmachine_id,round(avg(if(activity_type='start',-timestamp,timestamp))*2,3) as processing_time
fromactivity
group bymachine_id;

员工奖金

577. 员工奖金 - 力扣(LeetCode)

左连接,注意null不是0

selectname,bonus
fromemployee left join bonus using(empId)
where bonus<1000 or bonus is null;

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

1280. 学生们参加各科测试的次数 - 力扣(LeetCode)

要查询出每个学生参加每一门科目测试的次数,即对象是每个学生和每个科目,所以需要学生和科目先做一个笛卡尔乘积,然后和考试表左连接,按学生科目分组统计考试表中的对应次数

selectstudent_id,student_name,subject_name,count(examinations.student_id)as attended_exams
fromstudents cross join subjects left join examinations using(student_id,subject_name)
group bystudent_id,subject_name
order bystudent_id,subject_name;

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

570. 至少有5名直接下属的经理 - 力扣(LeetCode)

自连接,按员工id分组,having用于分组后筛选

select e1.name
from employee e1 join employee e2
one1.id=e2.managerId
group bye1.id
having count(*)>=5;

确认率

1934. 确认率 - 力扣(LeetCode)

左连接按user_id分组,用avg计算,如果确认的为真,那么就是1,否则就是0,没有的就是null变0

selects.user_id,round(ifnull(avg(c.action='confirmed'),0),2) as confirmation_rate
fromsignups s left join confirmations c
on s.user_id=c.user_id
group bys.user_id;

聚合函数

有趣的电影

620. 有趣的电影 - 力扣(LeetCode)

id&1判断奇数,<>不相等

select*
fromcinema
whereid&1 and description <> 'boring'
order byrating desc;

平均售价

1251. 平均售价 - 力扣(LeetCode)

左连接,匹配条件就是id相等并且日期对应,然后分组计算

selectp.product_id,round(ifnull(sum(p.price*u.units)/sum(u.units),0),2) as average_price
fromprices p left join unitsSold u
onp.product_id=u.product_id
andu.purchase_date between p.start_date and p.end_date
group byp.product_id;

项目员工 I

1075. 项目员工 I - 力扣(LeetCode)

按员工id左连接,按项目id分组取工作年限的平均值

selectproject_id,round(avg(experience_years),2) as average_years
fromproject left join employee using(employee_id)
group byproject_id;

各赛事的用户注册率

1633. 各赛事的用户注册率 - 力扣(LeetCode)

用不上连接,用子查询

selectcontest_id,round(count(*)*100/(select count(*)from users),2) percentage
fromregister
group bycontest_id
order bypercentage desc,contest_id;

查询结果的质量和占比

1211. 查询结果的质量和占比 - 力扣(LeetCode)

按query_name分组,统计质量的平均值,统计占比

selectquery_name,round(avg(rating/position),2) quality,round(avg(if(rating<3,1,0))*100,2) poor_query_percentage
fromqueries
group byquery_name;

每月交易 I

1193. 每月交易 I - 力扣(LeetCode)

date_format()函数,注意%Y是2025,而%y是25,%M是英文月份,%m是12

selectdate_format(trans_date,'%Y-%m') month,country,count(*) trans_count,sum(if(state='approved',1,0)) approved_count,sum(amount) trans_total_amount,sum(if(state='approved',amount,0)) approved_total_amount
from transactions
group bymonth,country;

即时食物配送 II

1174. 即时食物配送 II - 力扣(LeetCode)

子查询查找首发订单,然后在首发订单中计数即时订单,注意子查询要同时记录用户id,不然会误判其他用户的首发订单

selectround(avg(if(order_date=customer_pref_delivery_date,1,0))*100,2)as immediate_percentage
fromdelivery 
where(customer_id,order_date) in (select customer_id,min(order_date)fromdeliverygroup bycustomer_id);

游戏玩法分析 IV

550. 游戏玩法分析 IV - 力扣(LeetCode)

用子查询找出有从首次登录连续登录2次的玩家个数,除以总玩家

selectround(count(*)/(selectcount(distinct player_id)fromactivity),2) fraction
fromactivity
where(player_id,date_sub(event_date,interval 1 day)) in (selectplayer_id,min(event_date)fromactivitygroup byplayer_id);

排序和分组

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

2356. 每位教师所教授的科目种类的数量 - 力扣(LeetCode)

按教师分组统计唯一科目id

selectteacher_id, count(distinct subject_id) cnt
fromteacher
group byteacher_id;

查询近30天活跃用户数

1141. 查询近30天活跃用户数 - 力扣(LeetCode)

按日期分组,保留合法日期,统计唯一用户数

selectactivity_date day,count(distinct user_id) active_users
fromactivity
group byactivity_date
havingdatediff('2019-07-27',activity_date) between 0 and 29;

销售分析 III

1084. 销售分析 III - 力扣(LeetCode)

销售表左连接产品表,按产品分组,保留合法日期的

selectproduct_id,product_name
fromsales left join product using(product_id)
group byproduct_id
havingmin(sale_date)>='2019-01-01' and max(sale_date)<='2019-03-31';

超过5名学生的课

596. 超过 5 名学生的课 - 力扣(LeetCode)

按课分组,保留行数大于5的

selectclass
fromcourses
group byclass
havingcount(*)>=5;

求关注者的数量

1729. 求关注者的数量 - 力扣(LeetCode)

按用户分组,统计行数,按用户升序

selectuser_id ,count(*) followers_count
fromfollowers
group byuser_id
order byuser_id;

只出现一次的最大数字

619. 只出现一次的最大数字 - 力扣(LeetCode)

先用子查询找出只出现一次的数字,然后找最大值,注意from后面使用子查询需要给子表别名

selectmax(num) num
from(selectnumfrommyNumbersgroup bynumhavingcount(*)=1
) as t;

买下所有产品的客户

1045. 买下所有产品的客户 - 力扣(LeetCode)

按客户分组统计购买的产品数量是否等于所有的产品种类,注意用户可能重复购买

selectcustomer_id
fromcustomer
group bycustomer_id
havingcount(distinct product_key)=(select count(*) from product);

高级查询和连接

每位经理的下属员工数量

1731. 每位经理的下属员工数量 - 力扣(LeetCode)

自己按上级id和员工id内连接,然后按上级id分组,统计行数就是员工数量

selectm.employee_id,m.name,count(*) reports_count,round(avg(e.age)) average_age
fromemployees e join employees m
one.reports_to=m.employee_id
group bye.reports_to
order bym.employee_id;

员工的直属部门

1789. 员工的直属部门 - 力扣(LeetCode)

是Y的或者只有一个的

selectemployee_id,department_id
fromemployee
whereprimary_flag='Y' or employee_id in(selectemployee_idfromemployeegroup byemployee_idhavingcount(*)=1);

判断三角形

610. 判断三角形 - 力扣(LeetCode)

最小的两边之和大于最大边

selectx,y,z,if(x+y+z>2*greatest(x,y,z),'Yes','No') triangle
fromtriangle;

连续出现的数字

180. 连续出现的数字 - 力扣(LeetCode)

官解很无趣没有通用性,下面是deepseek给出的通用解法

如果数字是连续出现的,那么数字的行号和和出现顺序的差值是固定的,按数字和计算的差值分组统计次数

SELECT DISTINCT num AS ConsecutiveNums
FROM (SELECT num,id - ROW_NUMBER() OVER (PARTITION BY num ORDER BY id) AS grpFROM Logs
) t
GROUP BY num, grp
HAVING COUNT(*) >= 3;

指定日期的产品价格

1164. 指定日期的产品价格 - 力扣(LeetCode)

先查出每个产品在指定日期之前的最大日期

如果最大日期为空那么就是10,否则就取对应的价格

selectp1.product_id,ifnull(p2.new_price,10) price 
from(selectdistinct product_idfrom    products
) as p1 left join (selectproduct_id,new_pricefromproductswhere(product_id,change_date) in (selectproduct_id,max(change_date)from productswherechange_date<='2019-08-16'group byproduct_id)
) as p2
using(product_id);

最后一个能进入巴士的人

1204. 最后一个能进入巴士的人 - 力扣(LeetCode)

统计每一个人前面人的总重,保留合适的重量,再按顺序逆序取第一个

selecta.person_name
fromqueue a,queue b
wherea.turn>=b.turn
group bya.person_id
havingsum(b.weight)<=1000
order bya.turn desc
limit 1;

按分类统计薪水

1907. 按分类统计薪水 - 力扣(LeetCode)

用sum统计范围内的个数,再用union合并起来

select'Low Salary' category,sum(income<20000) accounts_count
fromaccounts 
union
select'Average Salary' category,sum(income between 20000 and 50000) accounts_count
fromaccounts 
union
select'High Salary' category,sum(income>50000) accounts_count
fromaccounts;

子查询

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

1978. 上级经理已离职的公司员工 - 力扣(LeetCode)

挺直接的

selectemployee_id
fromemployees
wheresalary<30000 and manager_id not in(selectemployee_idfromemployees)
order byemployee_id;

换座位

626. 换座位 - 力扣(LeetCode)

窗口函数lead往后取,lag往前取,需要over定义窗口的范围

lead往后取没有了就默认本值

selectid,if(id%2,lead(student,1,student)over(order by id),lag(student,1)over(order by id)) student
fromseat;

电影评分

1341. 电影评分 - 力扣(LeetCode)

这算两道题,注意用union all连接,如果用union会去掉相同的结果

三张表,都是用来两两连接查询名字的

第一个按用户分组保留数量最多的,第二先筛日期然后按电影分组保留平均分最高的

(selectname results
frommovieRating left join users using(user_id)
group byuser_id
order bycount(*) desc, name
limit 1)
union all
(select title results
frommovieRating left join movies using(movie_id)
wherecreated_at between '2020-02-01' and '2020-02-29'
group bymovie_id
order byavg(rating) desc,title
limit 1);

餐馆营业额变化增长

1321. 餐馆营业额变化增长 - 力扣(LeetCode)

用窗口函数按日期排序每七个算一次总和,最后从第七天开始挑

selectdistinct visited_on,sums amount,round(sums/7,2) average_amount
from(selectvisited_on,sum(amount)over(order by visited_on range interval 6 day preceding) sumsfrom customer
) t
wherevisited_on>= (select min(visited_on) from customer)+6;

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

602. 好友申请 II :谁有最多的好友 - 力扣(LeetCode)

将发送和接收合并在一起,统计最多的

selectid,count(*) num
from(selectrequester_id id, accepter_id a_idfromrequestAcceptedunion allselectaccepter_id id, requester_id a_idfromrequestAccepted    
) t
group byid
order bynum desc
limit 1;

2016年的投资

585. 2016年的投资 - 力扣(LeetCode)

顾名思义,两个子查询筛选条件

子查询如果参与from需要加上别名

selectround(sum(tiv_2016),2) tiv_2016
from(select tiv_2016 from insurance iwhere tiv_2015 in(select tiv_2015 from insurance where pid!=i.pid)and (lat,lon) not in(select lat,lon from insurance where pid!=i.pid)
)t;

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

185. 部门工资前三高的所有员工 - 力扣(LeetCode)

查出该部门前三高的工资,保留工资在里面的员工

注意这个版本不能在in后面的子查询用limit,所以要套一层

selectd.name department,e.name employee, salary
fromemployee e left join department d
one.departmentId=d.id
wheresalary
in( select * from(select distinct salaryfrom employeewhere departmentId=e.departmentIdorder by salary desc limit 3)t
);

高级字符串函数

修复表中的名字

1667. 修复表中的名字 - 力扣(LeetCode)

调用函数

concat连接字符串

upper变大lower变小

substring提取子串

selectuser_id,concat(upper(substring(name,1,1)),lower(substring(name,2))) name
fromusers
order byuser_id;

患某种疾病的患者

1527. 患某种疾病的患者 - 力扣(LeetCode)

字符串匹配

select*
frompatients
whereconditions like 'diab1%' or conditions like '% diab1%';

按日期分组销售产品

1484. 按日期分组销售产品 - 力扣(LeetCode)

group_concat可以将分组后的数据拼接成字符串

selectsell_date,count(distinct product) num_sold,group_concat(distinct product order by product separator ',') products
fromactivities
group bysell_date
order bysell_date;

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

1327. 列出指定时间段内所有的下单产品 - 力扣(LeetCode)

连接两张表,筛选时间,用产品分组挑总数超过100的

selectproduct_name,sum(unit) unit
fromorders left join products using(product_id)
whereorder_date between '2020-02-01' and '2020-02-29'
group byproduct_id
having unit >=100;

正则表达式 

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

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

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

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

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

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

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

\w :匹配一个字母数字字符(包括下划线)

.:匹配任意一个字符

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

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

查找拥有有效邮箱的用户

1517. 查找拥有有效邮箱的用户 - 力扣(LeetCode)

正则表达式regexp,\\用于表示\

select*
fromusers
wheremail regexp '^[a-zA-Z][\\w.-]*@leetcode\\.com$';

子句

删除重复的电子邮箱

196. 删除重复的电子邮箱 - 力扣(LeetCode)

注意要从数据库中删除,不允许在DELETE语句的子查询中直接引用正在被删除的表,防止在修改表的同时又查询它可能导致的不确定行为

所以要套一层select*from做临时表

delete fromperson
where id not in(select * from(selectmin(id)fromperson pgroup byemail            ) temp);

第二高的薪水

176. 第二高的薪水 - 力扣(LeetCode)

要注意没有需要返回null,因此外面再套一层select

select(select distinctsalaryfromemployeeorder bysalary desclimit 1 offset 1) secondHighestSalary;

http://www.xdnf.cn/news/4463.html

相关文章:

  • C语言编程--递归程序--Hanoi塔
  • 企业智能化第一步:用「Deepseek+自动化」打造企业资源管理的智能中枢
  • MEGA3:分子进化遗传学分析和序列比对集成软件
  • 检测内存条好坏有工具,推荐几款内存检测工具
  • github+ Picgo+typora
  • OpenCV提取图像中的暗斑/亮斑
  • IvorySQL 再次走进北京大学研究生开源公选课
  • onenet连接微信小程序(mqtt协议)
  • 【国产化】在银河麒麟ARM环境下离线安装docker
  • Spring 如何解决循环依赖问题?
  • JavaScript性能优化:从青铜到王者的进阶之路
  • 从人体姿态到机械臂轨迹:基于深度学习的Kinova远程操控系统架构解析
  • Kubernetes(k8s)学习笔记(九)--搭建多租户系统
  • QMK键盘固件配置详解
  • 2025.05.07-华为机考第三题300分
  • DIFY教程第四弹:通过工作流来创建一个SQL语句的执行器
  • 【计算机基础】任意进制转换方法详解
  • 资产管理系统对比评测:从传统模式到 AI 驱动的变革
  • 引用的使用
  • [Es_1] 介绍 | 特点 | 图算法 | Trie | FST
  • 【C/C++】errno/strerror 和 GetLastError()/FormatMessage 的区别
  • 模拟设计中如何减小失配
  • 4.系统定时器基本定时器
  • 操作系统——第四章(文件的物理结构以及与逻辑结构的对比)
  • Redis相关命令详解与原理
  • 【Agent】使用 Python 结合 OpenAI 的 API 实现一个支持 Function Call 的程序,修改本机的 txt 文件
  • 如何检查 Watchtower 是否正常工作及更新未生效的排查方法【日常排错】
  • 探寻程序开发的个人密码
  • excel 批量导出图片并指定命名
  • Excel点击单元格内容消失