leetcode数据库题解(一)
本想很早就写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,如下图:
![](https://img.haomeiwen.com/i14960611/d0221fba1247017a.png)
![](https://img.haomeiwen.com/i14960611/c8e24b1ec316dcdb.png)
今天就写这么多!寒冬也要加油呀!最后喝点鸡汤,非常感谢陌生的你(id:然)给我的安慰!
![](https://img.haomeiwen.com/i14960611/3e379d6d93c8267f.png)