leetcode题解(SQL)(5)

|| 写在前面
要说今天刷题收获的话:

  • 1 就是不要提前去看答案,顺着自己的思路多摸索摸索,逻辑链会一点点完善最后通畅
    退一步说,如果实在不会后看了没人的思路,就千万不要看别人的代码!再退一步说,如果看了别人的代码,就千万别只看一半!要看完!
  • 2 还有一些 常用操作的补充
    》处理表:辅助表,内外联结和自联结
    》基操:删除自联结的表时delete后需要加上一个副表名,ifnull()函数,is null 条件判断,涉及去重计数时count()里面就不能随便扔个*号了 (注意:没有count(distinct *)写法)

题一:编写一个 SQL 查询,满足条件:无论 person 是否有地址信息,都需要基于两表提供 person
的以下信息:
FirstName, LastName, City, State

解题思路:使用左外联结(Person作为左表) > > > 用时:60ms 内存:0B

select FirstName, LastName,City,State
from person left join address on Person.PersonId = Address.PersonId;

题二:查询第二大的数

解题思路一:返回去掉最大值后的表的最大值 > > > 用时:143ms 内存:0
解题思路二:limit语句挑出第二大值,isfull处理null情况 > > > 用时:109ms 内存:0

select max(Salary) as SecondHighestSalary from Employee 
where Salary != (select max(Salary) as SecondHighestSalary from Employee);

select ifnull(
(select distinct Salary  from Employee order by Salary desc limit 1,1), null) as SecondHighestSalary;

题三:求第N高的薪水

解题思路一:同上思路二 > > > 用时:148ms 内存:0

CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
  if N<0 then    
    RETURN (select min(Salary) from Employee);
  else   
    set N = N-1;
    RETURN (
        # Write your MySQL query statement below.
        select ifnull((select distinct Salary from Employee order by Salary desc limit N,1),null) as NthHighestSalay 
    );
  end if;
END

题四:编写一个 SQL 查询来实现分数排名。如果两个分数相同,则两个分数排名(Rank)相同。
请注意,平分后的下一个名次应该是下一个连续的整数值。换句话说,名次之间不应该有“间隔”。

题五:Employee 表包含所有员工,他们的经理也属于员工。每个员工都有一个 Id,此外还有一列对应
员工的经理的 Id。

解题思路一:使用内连接把经理扔到右边去,再通过自联结筛选满足条件的员工 用时:263ms 内存:0B

select a.name as employee  
from employee a inner join employee b 
on a.ManagerId=b.Id and a.salary > b.salary;

题六:编写一个 SQL 查询,查找 Person 表中所有重复的电子邮箱。

解题思路一:自联结查询 > > > 用时:556 ms (极慢)内存:0B
解题思路二:内联结+自联结 > > > 用时:193 ms 内存:0B
解题思路三:创建一个辅助表 > > > 用时:150ms 内存:0B
解题思路四:分组后having筛选

select distinct email from person a where email in (select email from person b  where a.id != b.id);

select distinct a.email from person a inner join person b on a.email = b.email and a.id != b.id;

select email from (select email, count(*) as num from person group by email)as a where num > 1;


select email
from person
group by email
having count(*) > 1;

题七:某网站包含两个表,Customers 表和 Orders 表。编写一个 SQL 查询,找出所有从不订购任何东西的客户

解题思路一:稀奇古怪顺手就用了两个表自联结形成辅助表 > > > 用时:233ms 内存:0B
解题思路二:用 is null 逻辑判断符 (注意不是 =null) > > > 用时:260ms (较慢)内存:0B

select name as customers from customers as c where c.id not in (select new.Id from (select a.id as id from customers a right join orders b on a.id= b.customerid) as new);

select name as customers from customers a left join orders b on a.id = b.customerid where customerid is null;

题八:编写一个 SQL 查询,来删除 Person 表中所有重复的电子邮箱,重复的邮箱里只保留 Id 最小 的那个。

解题思路一:按部就班,只查询出不重复的邮箱 或 重复了但id最小的邮箱
解题思路二:用delete 自联结删除其中一个表中的行就行

select * from person a 
where email not in (select a.email from person a group by email having count(*) > 1) 
or 
(email in (select a.email from person a group by email having count(*) > 1) 
and a.id < any(select b.id from person b where a.email = b.email) );


DELETE P1 
FROM Person P1, Person P2
WHERE P1.Email = P2.Email
AND P1.Id > P2.Id

题九:给定一个 Weather 表,编写一个 SQL 查询,来查找与之前(昨天的)日期相比温度更高的所有日期的 Id

解题思路一:日期比较datediff()函数 用时:286ms(快) 内存:0

select a.id from weather as a, weather as b where a.temperature>b.temperature 
and
DATEDIFF(a.RecordDate, b.RecordDate) = 1;

题十:有一个courses 表 ,有: student (学生) 和 class (课程)。
请列出所有超过或等于5名学生的课。
解题思路一:注意学生重复选择一门课的情况,在去重计数时 不能使用count(distinct *)

--错误写法!
select class from courses group by class having count(*) >= 5;

--right
select class from courses group by class having count(distinct student) >= 5;
发布了49 篇原创文章 · 获赞 77 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/a13352912632/article/details/104473914