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

10 力扣练习题

10 力扣练习题

文章浏览I

image

查询所有浏览过自己文章的作者。结果按照作者的 id 升序排列。

image

 注意:

1. 去重用distinct或者group by

2. 升序 从小到大是 asc; 降序 从大到小是 desc

员工奖金

image

select * from (select name, bonus from Employee a left join Bonus b on a.empId=b.empId) c where c.bonus is null or c.bonus<1000;

注意:这里一定是is null 而不是 bonus=null 如果这样写等价于false

image

 按分类统计薪水【2次】

image

 我的原始版本,这里面最严重的错误就是插入表格写错。这里只有一列,但我这样写插入的应该是三列的数值。

image

注意,这里的Create不是用{} 而是要用()。并且最后要有分号结尾,表格字段的最后一行不要有逗号,其余的行的列名都要有逗号作为结尾。

image

 并且力扣是只能够写一条查询语句的,所以我学习到了select union all这个语法,可以构建一个临时的表。

image

注意这个UNION ALL 后面直接接你要加的列值就行,如果是多列也不需要括号括起来:

image

这里我用这个语句代替了我的表构建,但是还是不对的,如果按照我原先的顺序:

image

 首先第一个错误,这里a和b都有category所以应该说明展示的是谁的category列,否则select不知道去查谁的。

此外,如果Accounts是我的左表,我其实这里是没有Average Salary的,那么连接之后就只会展示出仅有的两个类别:

image

 所以我将临时表放在左边进行连接,但这里还是错了。

image

 结果还是不对的,我如果使用的是count(*):

image

所以其实我们应该有正确的写法:

image

image

 有更加精简的答案:

image

 查询近30天活跃用户数

image

image

 这个是我的最开始的SQL语句,这里为了去重注意要使用distinct。日期的范围注意使用between and来限制范围并且要使用''单引号框起来,并且日期是两位,要用07这样的两位填充。

WHERE 必须在 GROUP BY 之前

image

 包含27的三十天要往前29天这个细节也没有注意到。

image

image

image

 买下所有产品的客户

image

 我最开始是这样写的,因为我不知道怎么看是否购买了所有的产品,所以我只能够看数量是否等于所有的产品数量。

image

 但后来我发现这样有的同一个客户买同一个产品有重复的,所以还需要对客户表去重,但我不会整行去重,学习一下:

image

image

 但是我发现题解的一个更加简单的方法,我现在其实可以在分组后直接在having中去重,因为此时已经分组了,那么只需要对表中的产品列去重就好:

image

 但是这个其实有点投机取巧,还有更加完美的办法:

image

2016年的投资

image

 我的写法:

image

 注意:这里必须要用concat中间加一个连接符,否则lat=1,lon=23;lat=12,lon=3。这种情况会被排除出去。

看到一个更加简单的窗口函数实现的:

image

 这个with t as 可以创建一个临时表格

image

 上升的温度

image

 一开始我是使用的left join 把表跟前面一行表格连接。后来发现要按照日期排序然后再连接,又要重新对排序后的赋予新的ID,这样比较复杂:

select a.id Id from (select *,rank() ID from Weather order by recordDate) a left join (select *,rank() ID from Weather order by recordDate) b on a.ID-1=b.ID where a.Temperature > b.Temperature;

这里的rank()还写错了,rank()必须要搭配窗口使用

rank() over(group by xxx order by xxx)

image

 但是这样还有一个问题:这里的题目的温度只能跟前一天的温度来比较,所以还要加一个判断

我首先就想到的 a.recordDate-b.recordDate=1但是这个不对31号使用。只能 DateDiff函数来计算日期差值:

image

 但其实也可以直接用 Lag窗口函数获取排序后的前一行数据:

# Write your MySQL query statement below
select temp.id Id from (select *,LAG(Temperature) over (order by recordDate) pre_Temperature, LAG(recordDate) over (order by recordDate) pre_recordDate from Weather ) temp 
where temp.Temperature > temp.pre_Temperature and datediff(temp.recordDate,temp.pre_recordDate)=1;

 即时食物配送II

image

 我首先写的是:

image

 但这里有个问题:

我们要区分一下having 和 where的区别:

image

temp.fisrt_orderdate=temp.order_date 这个条件应该放在where中,并且注意where 放在group by 之前。

image

 然后我就改为了这一版:

image

 这里又有问题了,为什么一定要group by customer_id,这和前面的count(temp.is_time)/count(*)冲突,因为这个我是想要计算得到一个值,而和group by在一起就会得到每个分组都有一个值。

这里其实是不需要按照每个客户端进行分组,因为每个人只会有一个首单,最后最终结果我修改为下面这种:

select round(count(temp.is_time)/count(*)*100,2) immediate_percentage from 
(select *, if(order_date=customer_pref_delivery_date,'yes',null) is_time,
first_value(order_date) over(partition by customer_id order by order_date) first_orderdate from Delivery) temp
where temp.first_orderdate=temp.order_date;

电影评分

image

 我最开始写的是这样:

image

 但是union 不能直接连接两个子查询,外面必须包一层

image

 并且我开始不知道order by里面可以写多个不同的排序方法,我就分开写,这样其实反而不好,会将里层排序好的又打乱重排。

并且注意还是老问题,select里面的语句要在group by中出现,最终答案:

image

第二高的薪水

image

 这个是我最开始写的:

image

 很严重一个问题就是在rank()里面不能写参数的。

image

 然后就改成这一版,但是没有满足没查询到返回null。

然后我想到了ifnull函数,改为了

image

但是这个也是有问题的,ifnull是存在这一行如果为null值则会赋值:

image

 但是这里是没有第二高的这个行返回null,这一行是不存在的,所以没有函数可以处理这种情况,只能外面套一个select。

image

image

 然后又发现一个问题,这里有的并列的两个排名都为2就会返回多行值,所以我又加了一个limit 1

image

 然后又发现一个问题,rank()排名,可能不产生第二名的编号:

image

image

image

image

 官方的解答:

image

 这里的offset是跳过几行,这里跳过第一行就会取第二个值,但是为什么跳过第一行就一定是第二高呢?因为:distinct会在order by之前执行!!所以是会先去重,然后再排序,这样就不可能产生并列的结果。

 员工的直属部门

image

注意这种写法: 

image

image

 注意:所以group by 不会返回所有的行 而是每一个类别随机返回一行,所以会丢失数据。

标准写法可以像我这个:我开始这里写的

or employee_id=(select em...) 但是这是不对的,因为这里的select返回的可能是多行一列的表,然后我就试了一下in原来可以用!
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(*)=1)

 指定日期的产品价格

image

 我最开始想到的就是用窗口函数,然后分区取每个产品的最后一个的修改日期然后对最后的日期判断。

image

 而且我开始还是用的group by 这是很严重的语法错误:

image

 所以要改一下分区的窗口

image

 这里我学习到窗口函数为查询结果中的每一行都计算一个值,而不会减少结果集的行数。

image

 这里我想用limit 1来取每个分区的第一行,然而limit不对分区作用,而是对整个区域。

image

 我就想着我用分组查询来把小于这个时期的先全部按组查出来,但犯了大错误!

image

 我这样写 每个类别只会给我返回一行,并不会按照我原有的想法返回。

image

按日期分组销售产品

image

image

 介绍一下group_concat函数:

image

image

image

image

image

image

 正确答案:这里我才知道couont里面也可以加distinct

image

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

image

image

image

image

 我最开始的写法:

image

 这里如果使用的count(*)就会计算有多少行,如果这一行是null也会计数进入,所以我们如果只要计某个列非null值,就要改为这个列的列名

其次,因为里面的temp是排序了的,但是我们发现外面展示出来的结果又没有序了,是因为外面做了group by 打乱了顺序,所以order应该放在最外面。

image

 餐馆营业额变化增长

image

image

image

 这里首先要学一个窗口函数

取当前行和前五行:ROWS between 5 preceding and current row --共6行
取当前行和后五行:ROWS between current row and 5 following --共6行
取前五行和后五行:ROWS between 5 preceding and 5 following --共11行
取当前行和前六行:ROWS 6 preceding(等价于between...and current row) --共7行
这一天和前面6天:RANGE between interval 6 day preceding and current row --共7天
这一天和前面6天:RANGE interval 6 day preceding(等价于between...and current row) --共7天
字段值落在当前值-100到+200的区间:RANGE between 100 preceding and 200 following  --共301个数值

image

 这行语句会自动帮你计算,比如第十天有两个行都是,但是它会自动按照最大的一行计算最终总和

image

 最终结果:

image

 注意前面用distinct去重

 每月交易I

image

image

 我最开始这样写的:

image

 但是count(表达式)也只会计算不是null的值,这个前面讲过了可以翻翻。所以approved_count并不会按照表达式来计算其实。

但其实可以这样搭配

image

 注意这个函数是date_format 不是mate

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

image

 这是我写的语句 但是有一个问题就是在经理没有在表格中的时候会返回null而不是无返回

image

image

 内连接inner join 只会返回匹配的行。

image

外连接 left/right join全部都返回。

image

正确的答案:

image