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

LeetCode的高频SQL50题(基础版)学习笔记

题目在此网站 https://leetcode.cn/

查询

image-20240726113841400

# Write your MySQL query statement below
select product_id
from products
where low_fats like 'Y'
and recyclable like 'Y';

image-20240726114111534

# Write your MySQL query statement below
select name
from customer
where referee_id !=2
or referee_id is null;

image-20240727112923703

# Write your MySQL query statement below
select name,population,area
from world
where population >= 25000000
or area >= 3000000;

image-20240727113242539

# Write your MySQL query statement below
select distinct(author_id) as id
from views
where author_id = viewer_id
order by id asc;

image-20240728145228877

# Write your MySQL query statement below
select tweet_id
from tweets
where char_length(content) > 15;
char_length()  : 求出字符的长度 

为什么不用length()呢 length是求字节长度的,

length(str)
(1)计算单位:字节
(2)utf8编码:一个汉字三个字节,一个数字或字母一个字节。
(3)gbk编码:一个汉字两个字节,一个数字或字母一个字节。


所以用length() 遇到汉字的话 不能准确计算字符的个数

连接

image-20240728150218786

# Write your MySQL query statement below
select unique_id,name
from employees es
left join EmployeeUNI eu
on es.id = eu.id;

image-20240729160411253

# Write your MySQL query statement below
select p.product_name,s.year,s.price
from sales s
left join product p 
on s.product_id = p.product_id

image-20240729160731202

# Write your MySQL query statement below
select distinct(customer_id),count(customer_id) as count_no_trans
from visits v 
left join transactions t 
on v.visit_id = t.visit_id
where transaction_id is null
group by customer_id

image-20240730105514645

# Write your MySQL query statement below
select w1.id as id
from weather w1,weather w2
where datediff(w1.recordDate,w2.recordDate)=1
and w1.temperature > w2.temperature

datediff是返回两个日期的差 datediff(a,b) = a-b 所以昨天和今天差一天 = 1

image-20240730105747789

# Write your MySQL query statement below

select machine_id,
round(sum(case when activity_type = 'end' then timestamp else - timestamp end)/count(distinct process_id),3) as processing_time
from activity
group by machine_id

对机械id进行分组,从而计算每个机械id的平均耗时,round(xxxxx,3)是保留三位小数

sum(case when activity_type = ‘end’ then timestamp else -timestamp)

因为是结束的时间戳减去开始的时间戳 所以结束时的时间戳是正的,开始的时间戳是负的。

最终求和是执行所有任务的执行时间

现在还差执行了几个任务的数据,count(distinct process_id) 就是求出执行了几个任务

image-20240731112740505

# Write your MySQL query statement below
select e.name as name,b.bonus as bonus 
from employee e
left join bonus b 
on e.empId = b.empId
where bonus is null
or bonus < 1000

image-20240731113215566

# Write your MySQL query statement below
select  stu.student_id as student_id,
        stu.student_name as student_name,
        sub.subject_name as subject_name,
        count(e.subject_name) as attended_exams
from students stu 
cross join subjects sub 
left join Examinations e 
on stu.student_id = e.student_id
and e.subject_name = sub.subject_name
group by stu.student_id,sub.subject_name
order by stu.student_id,sub.subject_name;

学生表与科目表交叉连接 产生两个表的笛卡尔积 因为每个学生都对应的科目都是一样的

再左连接这两个表的笛卡尔积 用student_id相连 并且 用subject_name 相连

因为要求出来每个学生的每个科目的测试次数 所以用student_id,subject_name 分组

排序也是一样。

image-20240801142617107

# Write your MySQL query statement below

select name
from employee
where id 
in(
select managerId
from employee
group by managerId
having count(id) >= 5)

首先子查询当中 找出来有至少5名下属经理的id 然后从父查询根据id找到经理的名字

image-20240801143721928

# Write your MySQL query statement below
select s.user_id as user_id,
round(ifnull(sum(case when action="confirmed" then 1 else 0 end)/count(action),0),2) as confirmation_rate
from signups s 
left join confirmations c 
on s.user_id = c.user_id
group by s.user_id;
round(,2) 保留两位小数 ifnull(,0) 如果是null 结果为0

求平均率(确认的行为/总的行为)所以 用到了

sum(case when action="confirmed" then 1 else 0 end)/count(action)

聚合函数

image-20240802114450958

# Write your MySQL query statement below
select *
from cinema
where description not like 'boring'
and id%2=1
order by rating desc

image-20240802114706418

# Write your MySQL query statement below
select p.product_id,
round(ifnull(sum(u.units*p.price)/sum(units),0),2) as average_price
from prices p  
left join unitssold u 
on p.product_id = u.product_id
where u.purchase_date between p.start_date and end_date or u.product_id is null
group by p.product_id
产品表与销售表相连接 因为每个时间段的产品售价都不一样
所以 where u.purchase_date between p.start_date and end_date
u.product_id is null 是因为有产品没有被购买 所以销售表没有销售数据 但是也要显示商品的平均售价
round(,2) 保留2位小数
ifnull(,0) 解决销售表为null的问题,如果为null,默认为0
平均售价 (不同时间的价格*不同时间的销量+不同时间的价格*不同时间的销量+....)/总销量
所以转为sql就是  sum(u.units*p.price)/sum(units)

image-20240803155912728

# Write your MySQL query statement below
select p.project_id,
round(avg(e.experience_years),2) as average_years
from project p 
left join employee e 
on e.employee_id = p.employee_id
group by p.project_id

image-20240803161044790

# Write your MySQL query statement below
select contest_id,
round(count(user_id)/(select count(*) from users)*100,2)  as percentage
from register 
group by contest_id
order by percentage desc , contest_id asc
round(,2)是保留两位小数,
因为以百分率显示,所以分母得称上100
分母统计出所有的用户人数
分子统计出注册赛事的用户人数 
然后对每个赛事分组
求出每个赛事的用户注册率
按照 percentage 降序 desc ,contest_id 升序 asc 可省略

image-20240804184529217

# Write your MySQL query statement below
select query_name,  
round(avg(rating/position),2) as quality, 
round(100*avg(rating<3),2) as poor_query_percentage
from queries
group by query_name
having query_name is not null;
query_name中 可能会有为名字为空的用户 所以用having query_name is not null筛选出来

avg(条件)相当于sum(if(条件,1,0))/count(全体)
进阶
sum(if(条件,N,0))/count(全体) 可用 N*avg(条件)代替
使用bool条件将多个样本判断为0和1,多个0和多个1的平均值就是1在整体中的比例,也即满足条件的样本在整体中的比例。

image-20240804185825907

# Write your MySQL query statement below
select left(trans_date,7) as month,
country,
count(*) as trans_count,
sum(case when state = 'approved' then 1 else 0 end) as approved_count,
sum(amount) as trans_total_amount,
sum(if(state='approved',amount,0)) as approved_total_amount
from transactions
group by month,country;
首先是查找每个月和每个国家的数据 所以对month,country分组
left(,7)从左边数截取7个字符
if(条件,真,假)

image-20240805105024494

# Write your MySQL query statement below
select round(sum(order_date=customer_pref_delivery_date)/count(*)*100,2) as immediate_percentage
from delivery
where (customer_id,order_date) in(
select customer_id,min(order_date)
from delivery
group by customer_id);
子查询当中 找出每个顾客的首次订单,将顾客id和首次订单日期传入父查询当中
然后父查询 求 即时订单率(即时订单数/总订单数)
即时订单(下单日期与期望配送日期同一天)
所以sum(order_date=customer_pref_delivery_date) 找出所有的即时订单

image-20240805111256496

# Write your MySQL query statement below
select round(avg(a.event_date is not null),2) as fraction
from  (
    select player_id, min(event_date) as login
    from Activity
    group by player_id
) p
left join Activity a
on p.player_id=a.player_id and datediff(a.event_date,p.login)=1
子查询当中 是查询每个用户的首次登录日期
与原表连接 条件为 首次登录日期和转天都有登录 
所以datediff(a.event_date,p.login)=1 找出这两天都有登录的用户
avg(a.event_date is not null) 找出结束日期不为空的。

排序和分组

image-20240806111101169

# Write your MySQL query statement below
select teacher_id,count(distinct subject_id) as cnt
from teacher
group by teacher_id;
因为大学老师 同一个科目会有多门课 用count(distinct subject_id) 来统计科目种类的数量

image-20240806111609597

# Write your MySQL query statement below
select activity_date as day ,
count(distinct user_id) as active_users
from activity 
where activity_date between '2019-06-28' and '2019-07-27'
group by activity_date
where activity_date between '2019-06-28' and '2019-07-27' 查询30天内
group by activity_date 每天活跃的用户数
count(distinct user_id) as active_users  因为用户每天可能会有多个记录 所以得用distinct 保留一个

image-20240807134522494

# Write your MySQL query statement below
select product_id,product_name
from sales
natural join product
group by product_id
having max(sale_date) <= '2019-03-31' and min(sale_date) >= '2019-01-01';

NATURAL JOIN 是 SQL 中的一个连接操作,它基于两个表中名称相同的列进行连接。在执行
NATURAL JOIN 时,SQL 会自动查找两个表中名称相同的列,并使用这些列作为连接条件。
对每个产品分组
如果最大日期和最小日期 在1-3月之间 证明这个产品只在这个日期内销售

image-20240807135618263

# Write your MySQL query statement below
select class
from courses
group by class
having count(*) >= 5;

image-20240809094208771

# Write your MySQL query statement below
select user_id,
 count(user_id) as followers_count
from Followers 
group by user_id
order by user_id asc

image-20240809095246566

# Write your MySQL query statement below
select if(count(num)=1,num,null) as num
from MyNumbers
group by num 
order by count(num) asc ,num desc
limit 1;
group by num  对数字分组
order by count(num) asc ,num desc 对每组数字进行计数,按每组数量升序排序,如果相同,再按数字大小降序排序  limit 1 取第一个
if(count(num)=1,num,null) 如果这组是一个数,就输入它,多个数返回null

image-20240810085942250

# Write your MySQL query statement below
select Customer_id
from Customer 
group by Customer_id 
having count(distinct product_key) =
(select count(*) from product)
子查询当中 统计了产品的总个数 
然后对每个用户购买的去重产品统计 如果个数相同则购买了全部商品

高级查询和连接

image-20240810090553822

# Write your MySQL query statement below
select e1.employee_id as employee_id,
e1.name as name,
count(e2.employee_id) as reports_count,
round(avg(e2.age),0) as average_age
from employees e1
left join employees e2
on e1.employee_id = e2.reports_to 
where e2.employee_id is not null
group by e1.employee_id
order by e1.employee_id
两张Employees表a和b自连接(经理至少有一位下属员工,自连接可以直接过滤出有下属员工的经理。如果用外连接,表中会包含没有下属员工的经理,需要用where语句再次过滤),a表信息作为经理,b表信息作为下属员工
对经理表的employee_id进行分组,计算出下属员工人数和平均员工年龄

image-20240811144924336

# Write your MySQL query statement below
select employee_id,department_id
from Employee 
where primary_flag = 'Y' or employee_id in(
    select employee_id
    from Employee
    group by employee_id
    having count(employee_id) = 1
)
子查询的作用就是找出员工只在一个部门的员工id
primary_flag为Y的 这两个条件能够找出所有的员工的直属部门

image-20240811145724198

# Write your MySQL query statement below
select 
    x,  
    y,
    z,
    case when x<y+z and y<z+x and z<x+y then 'Yes' else 'No' end as triangle
from triangle
组成三角形的条件:前两条边的和必须大于第三条边

image-20240814130803763

# Write your MySQL query statement below
select distinct l1.num as ConsecutiveNums
from logs l1,logs l2,logs l3
where l1.id = l2.id+1
and l2.id = l3.id+1
and l1.num = l2.num
and l2.num = l3.num; 
自链接三个表 l1代表第一个 ,l2代表第二个,l3代表第三个 并且这三次的数相等
然后去重 找到连续出现3次的数字

image-20240814131537419

# Write your MySQL query statement below
select distinct p1.product_id, ifnull(res.new_price, 10) as price
from Products p1
         left join
     (select product_id, new_price, change_date
      from (select product_id,
                   new_price,
                   change_date,
                   row_number() over (partition by product_id order by change_date desc) num
            from Products
            where change_date <= '2019-08-16') t
      where t.num = 1) res
     on p1.product_id = res.product_id

image-20240814132938273

image-20240815174724197

# Write your MySQL query statement below
select person_name
from (
    select turn,person_id,person_name,weight,sum(weight) over(order by turn asc) as total_weight
    from queue
    order by turn asc 
) q1
where total_weight<=1000
order by total_weight desc
limit 1;

image-20240815175926212

# Write your MySQL query statement below
select 'Low Salary' as category,count(*)as accounts_count from accounts where income<20000 
union
select 'Average Salary' as category,count(*) as accounts_count from accounts where income >=20000 and income <= 50000
union
select 'High Salary' as category ,count(*) as accounts_count from accounts where income > 50000;
 

image-20240821152441490

image-20240821152454562

# Write your MySQL query statement below
select employee_id
from employees 
where salary < 30000
and manager_id not in(
    select employee_id
    from employees
)
order by employee_id;

image-20240817212259915

# Write your MySQL query statement below
select if(id%2=0,id-1,if(id=(select count(distinct id)from seat),id,id+1)) as id,
  student
from seat 
order by id;
思路:偶数-1 奇数+1 如果总数是奇数 最后一位不变
所以if判断 是否偶数 如果是 id-1 不是再判断 是否为最后一位 如果是最后一位就不变,不是最后一位+1
偶数不用判断是否为最后一位 因为最后一位是偶数 学生总数也会是偶数

image-20240817214900257

image-20240817214909255

# Write your MySQL query statement below
(
    select u.name as results
    from movieRating m
    left join users u
    on u.user_id = m.user_id
    group by m.user_id
    order by count(movie_id) desc,u.name asc 
    limit 1
)
union all
(
    select mv.title as results
    from movieRating mr 
    left join movies mv 
    on mr.movie_id = mv.movie_id
    where date_format(mr.created_at,'%Y-%m') = '2020-02'
    group by mv.movie_id
    order by avg(mr.rating) desc,mv.title asc 
    limit 1
)

image-20240821152057320

image-20240821152122838

# Write your MySQL query statement below
select distinct visited_on,
    sum_amount as amount,
    round(sum_amount/7,2) as average_amount
from (
    select visited_on,
        sum(amount) over(order by visited_on rows 6 preceding ) as sum_amount
    from ( 
        select visited_on,
            sum(amount) as amount
        from customer
        group by visited_on
    ) TT
) LL
where datediff(visited_on,(select min(visited_on) from customer)) >= 6;
首先还是简要地理解一下窗口函数该怎么写,不过这次要多加一点点东西

[你要的操作] OVER ( PARTITION BY  <用于分组的列名>
                    ORDER BY <按序叠加的列名> 
                    ROWS <窗口滑动的数据范围> )
<窗口滑动的数据范围> 用来限定[ 你要的操作] 所运用的数据的范围,具体有如下这些:

当前行 - current row
之前的行 - preceding
之后的行 - following
无界限 - unbounded
表示从前面的起点 - unbounded preceding
表示到后面的终点 - unbounded following
举例理解一下:

取当前行和前五行:ROWS between 5 preceding and current row --共6行
取当前行和后五行:ROWS between current row and 5 following --共6行
取前五行和后五行:ROWS between 5 preceding and 5 folowing --共11行
本题中,要的是 按日期的, 金额的累计, 从当天算起共7天
则可理解成 我要的操作是‘累计金额’, 按序叠加的列是‘日期’, 窗口内的数据要‘取当前行和前6行’

不过即使前边的数据不够,窗口函数也会将范围内的数据框住并计算,因此需要最后手动地只要能够完整框住7天*的情况 【绊子1】
另外比较阴损的是,本题的数据中存在着同一用户在某日多次消费的情况,这样一来即使窗口照旧向前取6天就无法覆盖被挤出去的数据了,因此,需要构建一个小表格用来存放每天的金额总量 【绊子2】

image-20240829082635596

# Write your MySQL query statement below
select id,
    count(*) as num
from (
    select requester_id as id from RequestAccepted
    union all 
    select accepter_id as id from RequestAccepted
) t1 
group by id
order by num desc
limit 1;
简单来讲就是统计某个id在requester_id和accepter_id中出现的次数和。
直接使用union会合并重复数据,因此这里使用union all。
统计后排序再取表中第一项即可。

image-20240829083836321

# Write your MySQL query statement below
select 
    round(sum(tiv_2016),2) as tiv_2016
from (
    select 
    tiv_2016,
    count(*)over(partition by tiv_2015) as cn_2015, 
    count(*)over(partition by lat,lon) cn_l
    from insurance
) t 
where cn_2015 > 1 and cn_l = 1

image-20240830081832425image-20240830081854518

# Write your MySQL query statement below
select 
    department.name as department,
    e1.name as employee,
    e1.salary as salary
from employee as e1,department
where e1.departmentId = department.id 
and 3 > (
    select count(distinct e2.salary) 
    from employee as e2
    where e1.salary < e2.salary 
    and e1.departmentId = e2.departmentId 
)
order by department asc,salary desc;

高级字符串函数、正则表达式、子句

image-20240821153857059

# Write your MySQL query statement below
select user_id,
concat(upper(left(name,1)),lower(substring(name,2))) as name
from users
order by user_id asc;
# Write your MySQL query statement below
# 一、计算字段

# 其实本题主要考察的就是计算字段的使用。
# 二、知识点
# 2.1 CONCAT() 函数

# CONCAT 可以将多个字符串拼接在一起。
# 2.2 LEFT(str, length) 函数

# 从左开始截取字符串,length 是截取的长度。
# 2.3 UPPER(str) 与 LOWER(str)

# UPPER(str) 将字符串中所有字符转为大写

# LOWER(str) 将字符串中所有字符转为小写
# 2.4 SUBSTRING(str, begin, end)

# 截取字符串,end 不写默认为空。

# SUBSTRING(name, 2) 从第二个截取到末尾,注意并不是下标,就是第二个。

# CONCAT 用来拼接字符串 ● LEFT 从左边截取字符 ● RIGHT 从右边截取字符 ● UPPER 变为大写 ● LOWER 变为小写 ● LENGTH 获取字符串长度

image-20240826084638314

# Write your MySQL query statement below
select *
from patients
where conditions regexp '^DIAB1|\\sDIAB1';
'^DIAB1|\\sDIAB1'
匹配以DIAB1开头的或 空格+DIAB1

image-20240826085924453

# Write your MySQL query statement below
delete p1 
from person p1,person p2
where p1.email = p2.email and p1.id > p2.id;
where p1.email = p2.email and p1.id > p2.id;
找到 相同的邮箱名 并且 删除id较大的

image-20240827140305157

# Write your MySQL query statement below
select ifnull(
(select distinct salary as SecondHighestSalary
from employee
order by salary desc
limit 1,1)
,null) as SecondHighestSalary;

image-20240827141925410

# Write your MySQL query statement below
select sell_date,
   count(distinct product) as num_sold,
   group_concat(
    distinct product
    order by product asc
    separator ','
   ) as products
from activities
group by sell_date
order by sell_date;

image-20240828082723213

image-20240828082737168

# Write your MySQL query statement below
select p.product_name,
    sum(o.unit) as unit
from orders o 
left join products p 
on o.product_id = p.product_id
where o.order_date like '2020-02%'
group by p.product_name
having unit >= 100 


image-20240828083421067

# Write your MySQL query statement below
select *
from users
where mail regexp '^[a-zA-Z][a-zA-Z0-9_.-]*\\@leetcode\\.com$'

http://www.kler.cn/a/290175.html

相关文章:

  • OpenCV C++ 计算两幅图像之间的多尺度结构相似性(MSSIM)
  • QT版发送邮件程序
  • AI与OCR:数字档案馆图像扫描与文字识别技术实现与项目案例
  • 青藤深度参编的终端安全国家标准正式发布
  • MinerU容器构建教程
  • RTC精度及校准
  • 惠中科技RDS自清洁膜层:光伏领域的绿色革命
  • Spark MLlib模型训练—回归算法 Survival Regression
  • 【Selenium】Selenium运行时报cannot find Chrome binary错误的解决办吧
  • linux之网络子系统-MAC帧、数据报、段 的头部信息
  • 【C++】如何解决“pointer to incomplete class type is not allowed”。
  • 一篇文章讲清楚什么是Spring AOP
  • 从汇编角度分析C语言中的局部变量是如何产生的
  • pikachu文件包含漏洞靶场通关攻略
  • 运维管理体系及其实践要点:为高效运维保驾护航
  • zabbix通过OMSA监控Dell服务器_zabbix dell http
  • 为什么我会有使用gradle,需要花长时间去下载依赖?使用maven就不会有这种感受?
  • c++ websocket简单讲解
  • 大势智慧携“实景三维+AI”信创产品体系亮相2024中国地理信息产业大会
  • 详解 HTTPS 与 TLS证书链校验
  • 避坑之:深信服AC跨三层取MAC(核心交换机是锐捷S7808C_RGOS 11.0(4)B2P1)
  • 实验室ICPR 2024论文分享┆DS MYOLO:一种基于状态空间模型的驾驶场景可靠目标检测器
  • Edge资源占用优化:调整浏览器设置与关闭自动更新检查
  • 工业主板在轨道交通中的应用特点
  • 【网络】P2P打洞原理
  • 专项练习-数据思维-49题