美文网首页
LeetCode——数据库(一)

LeetCode——数据库(一)

作者: Miracle778 | 来源:发表于2019-11-23 20:35 被阅读0次

    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——数据库(一)

          本文链接:https://www.haomeiwen.com/subject/infkwctx.html