LeetCode——数据库(一)

LeetCode数据库部分的一些刷题记录


前言

秋招季的事情暂时告一段落了,闲了这么久,是时候重新学起来了。之前把操作系统和计网简单复习了下,趁现在有点闲时间,继续补强下数据结构、算法等基础知识。
准备刷LeetCode边练边复习,先整点简单的——LeetCode的数据库篇。之前在牛客上也有一个数据库专题,做也做了二三十道,但是时间有点久了,就不写了。
本篇就只记录在LeetCode上数据库部分做题的笔记


刷题

题目都在LeetCode上:https://leetcode-cn.com/problemset/database/
SQL语言用的是mysql

175、组合两个表 简单

这题就是连接两张表,查表1的FirstName,LastName和表2的City,State信息,不过要注意的是这里的题目条件,要用外连接而不能内连接。所以直接写左连接查询语句。

select 
    p.FirstName as FirstName,
    p.LastName as LastName,
    a.City as City,
    a.State as State
from 
    Person as p left join Address as a 
    on p.PersonId = a.PersonId

176、第二高的薪水 简单

这题目的是查询第二高的薪水,如果不存在则返回null。
第二高的话,排序之后直接用limit 1,1就好了,关键是这个不存在返回null,不存在又分为表数据不够,比如表只有一行。或者另一种情况,薪水全部一样,则也不存在第二高的薪水,因此这题除了按薪水降序排序外,还需要筛掉薪水相同的记录。可以像下面这样写使用group by或者用distinct + order by

select 
    Salary as SecondHighestSalary
from
    Employee
group by Salary desc
limit 1,1

但是这样写的话,不存在第二高记录的话会返回空而不是null,因此还需小小改动下。最终代码如下

select (
    select 
        Salary 
    from
        Employee
    group by Salary desc
    limit 1,1
) as SecondHighestSalary

177、第N高的薪水 中等

这题跟上一题差不多,不过是他把第二换成了第N,包装进一个函数里面去。不过话说回来,我这sql语句还没写过函数呢···。不过应该也就增删查改那几样。

create function getNthHighestSalary(N int) returns int
begin
    set N=N-1;
    return (
        select 
            Salary
        from 
            Employee
        group by Salary desc
        limit N,1
    );
end

这里注意的是第N高,limit写法是limit N-1,1,但是这样写要报语法错误,只能先用set把N赋值为N-1。


178、分数排名 中等

这题要把成绩按分数进行排名,分数降序排列倒是好办,但按照分数进行排名就有点绕了。之前在牛客上那个专题写过类似的题目,用到的是子查询,时间有点久了,有点忘了,看了看评论区老哥们的评论才绕出来。2333 T-T~

细心一点,把需求拆成子需求,分而治之 233~
这题要求输出两列,一列是分数降序排列Score,一列是分数排名(排名可并列)Rank。
分数排列查询语句
很简单,order by即可

select Score from Scores order by Score desc

排名查询语句
某个分数的排名等于有多少个大于等于它的分数的数量,用语句来写的话就是

select count(distinct Score) from Scores where Score >= s1.Score
# s1.Score是要进行排名的分数

综合一下,整个语句就是

select 
    s1.Score as Score,
    (
        select 
            count(distinct Score) 
        from 
            Scores 
        where Score>=s1.Score
    ) as Rank
from 
    Scores as s1
order by 
    s1.Score desc 

180、连续出现的数字 中等

找出表中连续出现3次以上的数字,这里注意是连续出现3次,如果只是出现次数大于3次的话,用count + group by 就好了,但是这里是连续出现,就意味着id必须要连续。
这题也是看评论看来的,看完醍醐灌顶,woc,原来这么简单啊,自己怎么想不到,枯了 T-T

连续出现次数大于3次,不必去数次数,利用连续这个点,3张表内连接,用值相等、Id连续条件进行限制,如果刚好出现次数等于3次的话,则该数在结果中出现一次,如果连续出现次数大于3次的话,该数会在结果里出现n-2(n>3)次,所以再加个distinct t1.Num限制。

select 
    distinct t1.Num as ConsecutiveNums
from 
    Logs as t1,
    Logs as t2,
    Logs as t3
where
    t1.Num = t2.Num and
    t2.Num = t3.Num and
    t2.Id = t1.Id+1 and
    t3.Id = t2.Id+1

181、超过经理收入的员工 简单

这题有点牛客上内味了,查询收入超过员工所属经理的员工的姓名。
注意这里的条件,一是员工收入超过经理,二是该员工是在该经理手下。
先左连接一下,连接条件是t1.ManagerId=t2.Id,然后就好办了,一个where条件的事情

select 
    t1.Name as Employee
from
    Employee as t1 left join Employee as t2 on t1.ManagerId=t2.Id
where
    t1.Salary > t2.Salary

182、查找重复的电子邮箱 简单

这题也太简单了吧,group by+having。

select 
    Email
from 
    Person
group by
    Email
having count(Email)>1

183、从不订购的客户 简单

这题也简单,客户表和订单表,找没有订单的客户名,直接用个not in美滋滋

select 
    t1.Name as Customers
from 
    Customers as t1
where
    t1.Id not in (
        select 
            CustomerId
        from
            Orders
    )

184、部门工资最高的员工 中等

这题本来以为挺容易的,两张表,员工表和部门表,本来以为两个表连接一下, 按部门group by + max就好了,但是写完之后发现好像差点意思,于是只能就地改改,代码改的非常丑。

select
    t2.Department as Department,
    t1.Name as Employee,
    t1.Salary as Salary
from
    Employee as t1,
    (   select
            t2.Name as Department,
            max(t1.Salary) as Salary,
            t2.Id as Id
        from 
            Employee as t1,
            Department as t2
        where
            t1.DepartmentId = t2.Id
        group by t2.Name 
    ) as t2
where
    t1.Salary = t2.Salary and
    t1.DepartmentId = t2.Id

上面代码就是相当于是,先把每个部门的部门名和最高薪水和部门ID查出来组成一个新表,然后再和Employee表连接。感觉写得有点太冗余了,代码太丑了,不过毕竟也不是搞DBA的,只求结果对就行了。。。


185、部门工资前三高的所有员工 困难

这题很容易能够写出不同部门的工资排名

select
    t1.DepartmentId as Id,
    t2.Name as Department,
    t1.Salary as Salary
from
    Employee as t1,
    Department as t2
where
    t1.DepartmentId=t2.Id
group by t2.Name,t1.Salary desc

但是如何按部门取分别的前三高这里卡了很久。

尝试了写函数,但是好像oj执行不了,报错。不知道这个函数这样写有没有用,oj执行不了,也不好调试。只能贴一下了。

create function getTop3(deptId int) returns int
begin
    return (
        select 
            t1.Salary as Salary
        from 
            Employee as t1,
            Department as t2
        where
            t1.DepartmentId = t2.Id and
            t1.DepartmentId = deptId
        group by t2.Name,t1.Salary desc
        limit 0,3  
    );
end

又尝试了下面这样写法,但是得到报错:This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'

select 
    t2.Name as Department,
    t1.Name as Employee,
    t1.Salary as Salary
from 
    Employee as t1,
    Department as t2
where
    t1.DepartmentId = t2.Id and
    t1.Salary in (
            select 
                e.Salary as Salary
            from
                Employee as e,
                Department as d
            where 
                e.DepartmentId = d.Id and
                d.Id=t1.DepartmentId
            group by d.Name,e.Salary desc
            limit 0,3
        )
order by t2.Name,t1.Salary desc

最后看了下官方题解,它的做法是对Employee表逐行进行判断是否符合条件,而且它的前三高判断没有用limit,而是转换了一下,变成比当前工资高的人不超过三个,则为前三。

select 
    t2.Name as Department,
    t1.Name as Employee,
    t1.Salary as Salary
from
    Employee as t1,
    Department as t2
where
    t1.DepartmentId = t2.Id and
    3 > (
            select 
                count(distinct Salary)
            from
                Employee
            where
                Salary>t1.Salary and
                DepartmentId = t1.DepartmentId
    )
order by t2.Name,t1.Salary desc

这一题做的有点混乱了,本来按自己的想法来说,前几前几这种问题,一般都是排好序之后用limit,但是好像很多题目都是两表连接,用比较符盒count判断,这个思路要学会转换。还有就是看了一些别人题解,发现也有用自定义变量等这些方法的,姿势还是很多的,哎,太菜了。


瞎说胡扯几句

闲着无事刷的几个题,本来以为leetcode那些上锁的题是通过刷题解锁的。。今天发现居然还要开会员才能解锁。
哎,反正也这么菜,先把免费的题刷了再考虑上锁的吧,然后今天下午知道原来leetcode上锁题要开会员才能解锁,想找个插件把上锁题隐藏起来的,但是只找到一个对英文官网有效的插件,于是又想着能不能找到几个Tamper脚本,找是找到了,但是好像并没啥luan用,不过倒是又引起了我对写TamperMonkey脚本的兴趣,想去搞两遍js然后写个leetcode隐藏上锁题的脚本,2333

今天只写了10题,后面看情况再更新吧。

你可能感兴趣的:(LeetCode——数据库(一))