当前位置:   article > 正文

力扣 SQL相关题目_力扣sql题

力扣sql题

目录

1 从不订购的客户

2 计算特殊奖金

3 删除重复的电子邮箱

4 修复表中的名字

5 按日期分组销售产品

7 丢失信息的雇员

8 每个产品在不同商店的价格

9 第二高的薪水

 逻辑法

limit关键字

窗口函数

10 上升的温度

11 股票的资本损益

12 销售分析

13 两人之间的通话次数

14 苹果和桔子

15 每月交易

16 购买了产品A、B但是没有买C的客户

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

18 换座位

19 连续空余座位

20 应该被禁止的用户

 21 每所学校最低录取分数

22 餐馆营业额变化增长


1 从不订购的客户

子查询方式

  1. select name Customers
  2. from Customers
  3. where id not in (
  4. select CustomerId from orders
  5. )

连接查询

  1. select c.name as Customers
  2. from Customers as c left join Orders as o on c.Id = o.CustomerId
  3. where o.Id is null

连接过程是这样的:Customers表左连接Orders表,所以Customers表是主表,将Customers表中的内容原封不动的抄下来

c.Id(o.customerid)

Name

1

Joe

2

Henry

3

Sam

4

Max

因为连接条件是c.id=o.customerid,数据库会利用笛卡尔积在Orders表中进行选择,将满足条件的结果添加到上面,注意这里我们是通过c.id和o.customerid进行连接的,所以两个表中的相应列现在合成了上面的一列

c.Id(o.customerid)

Name

o.Id

1

Joe

2

2

Henry

3

Sam

1

4

Max

因为c.id=3和c.id=1在两个表中都有,所以其o.id对应的值添加在上面的表中,对于o.id没有的,数据库会直接赋值为Null,所以最终连接结果表为

c.id(o.customerid)

Name

o.Id

1

Joe

2

2

Henry

Null

3

Sam

1

4

Max

Null

我们就是在上面这个连接表中进行查询的,利用where o.Id is null将那些没有订单的客户找出来

2 计算特殊奖金

使用条件语句控制奖金列的计算方式

这里的约束条件一是员工的ID是奇数,可以用%2!=0表示,姓名不以M开头可以表示为not like 'M%'或者left(name,1)!='M',

第一种是使用MySQL中的if语句,if(条件,语句1,语句2)如果条件成立执行语句1,否则执行语句2

  1. select employee_id,
  2. if (employee_id%2!=0 and name not like 'M%',salary,0) as bonus
  3. from employees
  4. order by employee_id

第二种是使用case when then else end语句

  1. select employee_id,
  2. case
  3. when employee_id%2!=0 and name not like 'M%'
  4. then salary
  5. else 0
  6. end as bonus
  7. from employees
  8. order by employee_id

3 删除重复的电子邮箱

 

 delete的另一种用法

  1. DELETE p1
  2. from person p1,person p2
  3. where p1.email=p2.email and p1.id>p2.id

4 修复表中的名字

 常用的字符串处理函数

concat():字符串连接

left(s,n):获取字符串左边第n个字符

lower()、upper():字符串大小写转换

substring(s,n):从字符串s第n个位置开始截取

  1. select user_id,concat(upper(left(name,1)),lower(substring(name,2))) as name
  2. from users
  3. order by user_id

5 按日期分组销售产品

group_concat官方DOC

 将一组非NULL结果以字符串连接的形式返回,如果有NULL值直接返回NULL,可指定连接元素的排列和分隔符,默认是升序和以‘,’分割

  1. select sell_date,
  2. count(distinct product) num_sold,
  3. group_concat(distinct product) products
  4. from activities
  5. group by sell_date
  6. order by sell_date

7 丢失信息的雇员

 

 

 两种解决方式

  1. select temp.employee_id
  2. from
  3. (select a.employee_id
  4. from employees a left join salaries b on a.employee_id=b.employee_id
  5. where b.salary is NULL
  6. union
  7. select b.employee_id
  8. from employees a right join salaries b on a.employee_id=b.employee_id
  9. where a.name is NULL) as temp
  10. order by temp.employee_id

union可以将两个结果表去重的合并在一起,那么先寻找姓名缺少再寻找工资缺失,然后通过union进行去重合并就能得到所有信息缺失的ID

  1. select
  2. employee_id
  3. from
  4. (
  5. select employee_id from employees
  6. union all
  7. select employee_id from salaries
  8. ) as t
  9. group by
  10. employee_id
  11. having
  12. count(employee_id) = 1
  13. order by
  14. employee_id;

将两个表合并到一起,然后根据ID分组,分组中ID数量为1的表示有信息缺失

8 每个产品在不同商店的价格

 

 

 宽表变长表

  1. select product_id,'store1' as store,store1 as price
  2. from products
  3. where store1 is not NULL
  4. union all
  5. select product_id,'store2' as store,store2 as price
  6. from products
  7. where store2 is not NULL
  8. union all
  9. select product_id,'store3' as store,store3 as price
  10. from products
  11. where store3 is not NULL

另外补充长表变宽表

  1. select product_id
  2. case when store='store1' then price else NULL end as 'store1',
  3. case when store='store2' then price else NULL end as 'store2',
  4. case when store='store3' then price else NULL end as 'store3'
  5. from products
  6. order by product_id

9 第二高的薪水

 

 逻辑法

第二就是小于第一的最大值

  1. select if(max(distinct salary) is not NULL,max(distinct salary),NULL) as SecondHighestSalary
  2. from Employee
  3. where salary<(
  4. select max(salary)
  5. from Employee
  6. )

limit关键字

MySQL中imit y offset x 分句表示查询结果跳过 x 条数据,读取前 y 条数据。

  1. select ifnull((
  2. select distinct salary
  3. from Employee
  4. order by salary desc
  5. limit 1 offset 1
  6. ),NULL) as SecondHighestSalary

窗口函数

  1. #外面select可以处理NULL
  2. select (
  3. select salary
  4. from
  5. (
  6. #利用窗口函数获取排名信息表
  7. select salary,
  8. #dense_rank当有并列排名时
  9. #下一个排名是接着上一个的排名
  10. #就像这样:112
  11. dense_rank() over (order by salary desc) rn
  12. from Employee
  13. ) as t
  14. #获取第二高,只返回一个
  15. where t.rn=2 limit 1
  16. ) SecondHighestSalary

10 上升的温度

 

 datediff(日期1,日期2)返回两个日期相差的天数

  1. # Write your MySQL query statement below
  2. select a.id
  3. from weather as a
  4. #当天温度比前一天高
  5. where a.temperature>(
  6. #获取前一天的温度
  7. select b.temperature
  8. from weather as b
  9. where datediff(a.recorddate,b.recorddate)=1
  10. )
  11. order by a.id

进行SQL优化,从笛卡尔积中取结果

  1. SELECT b.Id
  2. FROM Weather as a,Weather as b
  3. WHERE a.Temperature < b.Temperature and DATEDIFF(a.RecordDate,b.RecordDate) = -1;

11 股票的资本损益

 

 多表构造连接方式

  1. select a.stock_name,b.sell_money-a.buy_money as capital_gain_loss
  2. from
  3. (
  4. ##创建每只股票购买所花的钱数
  5. select stock_name,sum(price) as buy_money
  6. from stocks
  7. where operation='Buy'
  8. group by stock_name
  9. ) as a
  10. inner join
  11. (
  12. ##创建每只股票出售所获得的钱数
  13. select stock_name,sum(price) as sell_money
  14. from stocks
  15. where operation='Sell'
  16. group by stock_name
  17. ) as b on a.stock_name=b.stock_name

case语句

  1. select stock_name,
  2. sum(
  3. case operation
  4. when 'Buy' then -price
  5. else price
  6. end
  7. ) as capital_gain_loss
  8. from stocks
  9. group by stock_name

12 销售分析

 

  1. SELECT s.product_id, product_name
  2. FROM Sales s
  3. Left JOIN Product p
  4. ON s.product_id = p.product_id
  5. GROUP BY s.product_id
  6. HAVING MIN(sale_date) >= '2019-01-01' AND MAX(sale_date) <= '2019-03-31'

13 两人之间的通话次数

 

 A给B打,B也给A打的话,将回拨电话记录列进行交换,只以打电话中的一个人为中心进行分组统计

least()函数用来寻找一些值中最小的一个 ,group by 除了可以指定列名还可以使用表达式

  1. select from_id as person1,
  2. to_id as person2,
  3. count(from_id) as call_count,
  4. sum(duration) as total_duration
  5. from calls
  6. group by least(from_id,to_id),greatest(from_id,to_id)

14 苹果和桔子

 

聚合函数是用在整个分组上的,所以可以在其中控制分组中每一项的具体表达式

  1. select sale_date,sum(
  2. case fruit
  3. when 'apples' then sold_num
  4. else -sold_num
  5. end
  6. ) as diff
  7. from sales
  8. group by sale_date
  9. order by sale_date

15 每月交易

 带有条件的计数和求和,注意count中的or NULL条件

  1. select
  2. left(trans_date,7) as month,
  3. country,
  4. count(state) as trans_count,
  5. count(state='approved' or NULL) as approved_count,
  6. sum(amount) as trans_total_amount,
  7. sum(if(state='approved',amount,0)) as approved_total_amount
  8. from transactions
  9. group by country,year(trans_date),month(trans_date)

16 购买了产品A、B但是没有买C的客户

 

instr(A,B)可以在字符串A中搜索B如果包含B返回B首次出现的位置,否则返回0

  1. # Write your MySQL query statement below
  2. select customer_id,customer_name
  3. from customers
  4. where customer_id in (
  5. #统计买了产品A、B但是没有买C的ID
  6. select a.customer_id
  7. from (
  8. #统计每个用户的购买情况
  9. select customer_id,group_concat(distinct product_name) as times
  10. from orders
  11. group by customer_id
  12. ) as a
  13. #用instr进行筛选
  14. where instr(a.times,'C')=0 and instr(a.times,'A')!=0 and instr(a.times,'B')!=0
  15. )
  16. order by customer_id

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

 

 

 count(列名)时如果这个列所有的值都为NULL返回0,先交叉连接构建出学生和学科的对应关系然后左外连接考试信息表,进行分组,在每组进行统计

  1. SELECT a.student_id, a.student_name, b.subject_name, COUNT(e.subject_name) AS attended_exams
  2. FROM Students a CROSS JOIN Subjects b
  3. LEFT JOIN Examinations e ON a.student_id = e.student_id AND b.subject_name = e.subject_name
  4. GROUP BY a.student_id, b.subject_name
  5. ORDER BY a.student_id, b.subject_name

18 换座位

 直接改变ID

  1. select
  2. if(
  3. id%2=0,
  4. id-1,
  5. if(id=(select count(distinct id) from seat),
  6. id,
  7. id+1))
  8. as id,student
  9. from seat
  10. order by id

19 连续空余座位

 利用join进行表和自身的笛卡尔积,然后筛选出连续的、都是空闲的座位

  1. select distinct a.seat_id
  2. from cinema a join cinema b on
  3. #连续的座位
  4. abs(a.seat_id-b.seat_id)=1 and
  5. #都是空闲的
  6. a.free=1 and b.free=1
  7. order by a.seat_id

20 应该被禁止的用户

 

  1. SELECT DISTINCT a.account_id AS account_id
  2. #隐式自连接
  3. FROM LogInfo a, LogInfo b
  4. WHERE
  5. #某个用户
  6. a.account_id = b.account_id
  7. #异地登录
  8. AND a.ip_address != b.ip_address
  9. #一个还没下线
  10. AND a.logout <= b.logout
  11. #另外一个就进行了登录
  12. AND b.login <= a.logout

 21 每所学校最低录取分数

 

 连接中可以使用不等条件

  1. select
  2. school_id,
  3. #取最低分数,如果为null,则输出-1
  4. ifnull(min(score), -1) as score
  5. from
  6. Schools s left join Exam e
  7. #容量需大于分数段学生数量
  8. on capacity >= student_count
  9. group by school_id

22 餐馆营业额变化增长

 滑动窗口可以控制窗口的大小

当前行 - 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行

  1. elect
  2. visited_on,
  3. amount,
  4. average_amount
  5. from (
  6. select
  7. visited_on,
  8. #按照访问日期进行排序
  9. row_number() over(order by visited_on) as rk,
  10. #过去7天用rows指定
  11. #最外一层的sum是组内求和
  12. sum(sum(amount)) over(order by visited_on rows between 6 preceding and current row) as amount,
  13. round(avg(sum(amount)) over(order by visited_on rows between 6 preceding and current row), 2) as average_amount
  14. from Customer
  15. group by visited_on
  16. ) as base
  17. where rk >= 7
  18. order by visited_on

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/一键难忘520/article/detail/871970
推荐阅读
相关标签
  

闽ICP备14008679号