leetcode 数据库题 第三弹
- 584. 寻找用户推荐人
- 585. 2016年的投资
- 586. 订单最多的客户
- 595. 大的国家
- 596. 超过5名学生的课
- 601. 体育馆的人流量
- 602. 好友申请 II :谁有最多的好友
- 607. 销售员
- 608. 树节点
- 610. 判断三角形
- 小结
584. 寻找用户推荐人
https://leetcode.cn/problems/find-customer-referee/
嗯。。。又是用 ifnull、nvl 的基础题目,把无数据的行列出即可。
# mysql
select name from customer where ifnull(referee_id,0)<>2
# mssql
select name from customer where isnull(referee_id,0)<>2
# oracle
select name from customer where nvl(referee_id,0)<>2
CSDN 文盲老顾的博客,https://blog.csdn.net/superwfei
585. 2016年的投资
https://leetcode.cn/problems/investments-in-2016/
嗯。。。。这个题目描述的优点绕,其实翻译过来就两个条件,用 exists 和 not exists 把两个条件分别实现一下就可以。子查询需要把条件写的清晰才可以。
# 一拖三
select round(sum(tiv_2016),2) tiv_2016
from insurance a
where not exists(select 1 from insurance where lat=a.lat and lon=a.lon and pid<>a.pid)
and exists(select 1 from insurance where tiv_2015=a.tiv_2015 and pid<>a.pid)
586. 订单最多的客户
https://leetcode.cn/problems/customer-placing-the-largest-number-of-orders/
嗯,注意并列最多的情况,用 rank 排名函数辅助一下即可,结合 group 和 count(0) 就很轻松得到结果了。
# 一拖三,count(0) as cnt 不是必须的,可以删除掉
select customer_number
from (
select customer_number ,count(0) as cnt
,rank() over(order by count(0) desc) rid
from orders
group by customer_number
) a
where rid = 1
595. 大的国家
https://leetcode.cn/problems/big-countries/
。。。。不就是两个条件满足一个即可的么,这不就是一个简单的or么,这也可以做为题目出现?
# mysql && mssql
select name,population,area
from world
where area>=3000000
or population>=25000000
oracle 不知道为什么没能通过,一直提示数据类型错误?咱不熟悉,不了解,不知道,放弃 oracle 了
596. 超过5名学生的课
https://leetcode.cn/problems/classes-more-than-5-students/
不想讨论这个题目。
select class from courses
group by class having(count(0)>4)
601. 体育馆的人流量
https://leetcode.cn/problems/human-traffic-of-stadium/
总算又出现一个标注为困难的数据库题目了。简单来说,还是 180 的题目差不多,不过多要自己验证是否大于100出现连续,且要输出连续的片段。
# mysql && mssql
with t as (
select a.*,(case when a.people>= 100 then 1 else 0 end) isC,row_number() over(order by id) rid
,row_number() over(partition by (case when a.people>= 100 then 1 else 0 end) order by id) nid
from stadium a
)
select id,visit_date,people
from t a
inner join (
select isC,rid-nid fid from t group by rid-nid,isC having(count(0) > 2)
) b on a.isC=b.isC and a.rid-a.nid=b.fid
oracle 其实用这个指令也没问题,可以一拖三,但是,oracle 版本,日期格式包含了时间部分,所以提交没有通过,只好在追加一个转换函数。
然后一路提交,oracle 报错了好几次。。。最后才发现,没有审题清楚,人家还要求升序排列。。。。
with t as (
select a.*,(case when a.people>= 100 then 1 else 0 end) isC,row_number() over(order by id) rid
,row_number() over(partition by (case when a.people>= 100 then 1 else 0 end) order by id) nid
from stadium a
)
select id,to_char(visit_date,'YYYY-MM-DD') visit_date,people
from t a
inner join (
select isC,rid-nid fid from t group by rid-nid,isC having(count(0) > 2)
) b on a.isC=b.isC and a.rid-a.nid=b.fid
order by a.id
最后,题目里要求是 id 连续。。。。hmm,咱也没注意这个问题,懒得修改这个指令了。也就是说,第一次提交的指令,加上 order ,其实就是一拖三了。
602. 好友申请 II :谁有最多的好友
https://leetcode.cn/problems/friend-requests-ii-who-has-the-most-friends/
嗯,终于用到 union 了,就是基础的列转行,然后统计。
select id,num
from (
select a.id,count(0) as num,row_number() over(order by count(0) desc) rid
from (
select requester_id id
from requestAccepted
union all
select accepter_id
from requestAccepted
) a
group by a.id
) a
where rid=1
607. 销售员
https://leetcode.cn/problems/sales-person/
嗯,完全没有供职过,用 not exists 完成。
select name
from SalesPerson p
where not exists(
select 1 from orders o
inner join company c on o.com_id=c.com_id
where o.Sales_Id=p.Sales_Id and c.name='RED'
)
608. 树节点
https://leetcode.cn/problems/tree-node/
考虑到不需要划分层级,所以不用 cte 辅助,再考虑到子查询相对较慢,也同样弃用了,直接用 join 结合条件判断输出节点类型就完事。
select distinct t1.id
,(case when t1.p_id is null then 'Root'
when t2.id is null then 'Leaf'
else 'Inner'
end
) Type
from tree t1
left join tree t2 on t2.p_id=t1.id
order by t1.id
610. 判断三角形
https://leetcode.cn/problems/triangle-judgement/
嗯,x,y,z 都是已知的,求出最大边长,然后其他两边和大于最大长,就是符合的,子查询求出最大长,然后用计算列验证一下。
# mysql && mssql
select a.x,a.y,a.z,(case when a.x+a.y+a.z-a.mx > a.mx then 'Yes' else 'No' end) triangle
from (
select a.*,(select max(t.mx) from (select a.x as mx union all select a.y as mx union all select a.z as mx) t) as mx
from triangle a
) a
oracle 不知道怎么搞子查询变成列,所以没能通过。想其他小伙伴咨询一下,后续题目需要用子查询完成的,到时候再解决吧。
小结
在数据库中,查询指令才是最最最基础,最最最常用的指令,没有之一。
而 t-sql 贯穿了整个查询的部分,虽然有函数、方法不太一致的情况,但这些并不需要在意,就和大家都说汉语,有的带点河南口音,有的带点东北方言,还有的夹杂着闽南土话,差不多就这么个情况而已。
对于查询来说,最重要的起始就是条件筛选的逻辑。根据题目仔细摆一下条件内容,基本上都能够直接得到结果。最多就是组合查询,或者放到子查询,再了不起,用关联查询,一般都能解决。
而现在,oracle 、 mysql、mssql 都支持了排名函数,虽然这个暂时可能还不是 t-sql 的内容,但出奇的,使用方法完全一致。基本可以确定 mysql 肯定是抄别人的,至于 oracle 和 mssql 谁抄谁的,老顾也不了解。反正微软和苹果抄视窗可视化的官司,也不是啥新闻。