leetcode数据库题解(一)

凡例:1.对于题目只放出题目的编号、题目和链接;
2.题目按照通过率排序;
3.解答会放出mysql语言的代码,其他语言我没写过,就不放出来了。

#595大的国家

这题比较简单,用个where查询就可以了

select name,population,area from World where population>25000000 or area>3000000;

#182查找重复的电子邮箱

这题也不难,用count函数,重复的邮箱会大于1,注意用having关键词时必须和分组group by一起使用,并且放在group by之后。

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

当然这题也可以用子查询,即先计数,创造一个临时表。注意,这里子查询的表要给出一个别名,我们记为counting。

select Email from (select Email , count(Email) as num from Person group by Email) as counting where num>1;

#627交换性别

这题考update和case的用法。

update salary set sex=case sex when 'm' then 'f' else 'm';

当然也可以这么写。

update salary set sex=case sex when 'm' then 'f' when 'f' then 'm';

用if也是可以的。if函数和excel的if函数很像。

update salary set sex=if(sex='m' ,'f' , 'm');

#620有趣的电影

这题也很简单,用where判断条件就行了。注意结果要按降序(desc)排列,升序是asc。判断奇数用mod函数也可以:MOD(id,2)=1。不等于用<>也可以,但是大多数语言只支持'!='。

select * from cinema where id%2==1 and description!='boring' order by rating desc;

#175组合两个表

这题也很基础,考组合的用法。这题要求无论Person是否有地址信息,都需要给Person提供地址信息。也就是说即使Person中有些条目在Address中找不到匹配的,也要选出来,那么符合条件的就是左交(left join)了。

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

#181超过经理收入的员工

这类题要构造临时表,即把一个表用别名复制几次。第一个筛选员工,第二个表选出对应的manager。

select e1.Name as Employee from Employee e1,Employee e2 where e1.Salary>e2.Salary where e1.ManagerId=e2.Id; 

#183从不订购的客户

这题要从Customers表中筛选不在Orders表中的客户,可以延续上题的思路,先左交,再选出customerid为null的顾客。

select tmp.Name as Customers from 
(select Customers.Name,Orders.CustomerId as order as Customers from Customers left join Orders on Customers.Id=Orders.CustomerId) as tmp where tmp.order is null;

其实我上面写繁琐了,不需要用子查询,直接从组合的表中选择就好了。看别人的写法:

select c.Name as Customers from
 Customers c left join Orders o on c.Id=o.CustomerId 
where o.CustomerId is NULL;

注意这里在组合表后直接用了where,而且组合表中为空的CustomerId也可以用o.CustomerId引用。
不使用左交,用not in判断条件也是可以的。这种方法也比上面的简洁。

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

#626换座位

这题比较难,需要用case和子查询。注意,counts要在后面单独算出来,因为前面id,student是绑定的,用count(student)是不行的,因为在select中的count(student)就限定了结果只能有1行。

select(case
      when id%2!=0 and id!=counts then id+1
      when id%2!=0 and id=counts then id
      else id-1 end)
      as id,student
      from seat,(select count(student) as counts from seat)seatCount 
      order by id;

#178分数排名

这题也有难度,也要构建临时表。还是要注意不要在select下直接写count,要放在子查询下。
第一种思路是查询有多少不重复的分数大于当前分数。

select s1.Score,
(select count(distinct s2.Score)+1 from Scores s2 where s2.Score>s1.Score) as Rank 
from Scores s1 order by s1.Score desc;

第二种思路是构建两个变量,其中一个变量代表Rank的值,另一个变量代表上一个Score的值,当Score按从高到低排序后,只需要比较前一个 Score是否等于当前Score,如果相等,则Rank不变,如果不想等,则Rank加1。用户变量这一块我也不是非常清楚,这里先看看大神的代码吧。

select 
    Score,  
    @i := @i + (@j <> (@j:= Score)) as Rank 
from 
    Scores, (select @i:=0,@j:=-1) init 
order by Score desc

#196删除重复的电子邮箱

delete p1 from Person p1,Person p2 where p1.Email=p2.Email and p1.Id>p2.Id;

这题用到的delete和我们学的有点不一样,一般delete后面是不带表名的,表名在from后,这里from后有两个表名,指明p1就删除p1的内容并返回p1,p2同理,如果同时指明p1和p2,返回的是p1,p2各自删除后的内交inner join,如下图:


同时删除p1,p2

运行结果

还有另一种思路,就是用正常的delete,条件是它不是最小的Id,这就要用到子查询和group分组了。

delete from Person where Id not in (select Id from (select min(Id) as Id from Person group by Email) as tmp) ;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • MYSQL 基础知识 1 MySQL数据库概要 2 简单MySQL环境 3 数据的存储和获取 4 MySQL基本操...
    Kingtester阅读 7,857评论 5 116
  • 观其大纲 page 01 基础知识 1 MySQL数据库概要 2 简单MySQL环境 3 数据的存储和获取 4 M...
    周少言阅读 3,179评论 0 33
  • 坐在屋里看着阳光在窗外妩媚 冰冷的手划过湿润眼眸 思绪飞舞在记忆的废墟 离别不是伤愁的借口 对你的感觉渐渐消失 才...
    北国爱人阅读 188评论 0 0
  • - c o o l i n u - 原 创 时 尚 自 媒 体 + × 韩国性感小野马泫雅出道至今,性感的形象一直...
    coolinu阅读 1,671评论 0 1
  • 还是不能自律,懒癌复发。第一阶段考试过了,第二阶段时间更紧任务更重,加入007原本就是让自己更自律,成为少数人,这...
    吴世平阅读 219评论 0 0