https://leetcode.cn/problems/exchange-seats/
嗯,今天又看了看这个题目,发现用例已经修复了。
# mysql && oracle
select floor((id - 1) / 2) * 2 + row_number() over(partition by floor((id - 1) / 2) order by id desc) id ,student
from seat
# mssql
select (id - 1) / 2 * 2 + row_number() over(partition by (id - 1) / 2 order by id desc) id ,student
from seat
# mssql && mysql
# 这个是抄评论里的内容,可惜不直到怎么调整的能够支持 oracle
select rank() over (order by (id - 1) ^ 1) id, student
from Seat
https://leetcode.cn/problems/students-and-examinations/
额。。。统计所有人,所有科目,各进行了几次考核。。。那么人员和科目只能最大化交叉查询了,然后再去关联考试次数。
其实指令是一拖三的,把空值处理换成各自的函数即可:
oracle : nvl
mysql : ifnull
mssql : isnull
# oracle
select a.*,nvl(cnt,0) attended_exams
from (
select * from students,subjects
) a
left join (
select student_id,subject_name,count(0) cnt
from examinations
group by student_id,subject_name
) b on a.student_id=b.student_id and a.subject_name=b.subject_name
order by a.student_id,a.subject_name
CSDN 文盲老顾的博客,https://blog.csdn.net/superwfei
https://leetcode.cn/problems/restaurant-growth/
额。。。。根据日期进行关联,还得限定输出的日期范围,难度不高,就是写起来挺麻烦,这就已经接近日常工作的样子了。
主要的是 mysql 和 mssql 的 datediff 的用法,差异不小哦,需要仔细查询各自的语法和差计算方式,哪个日期在前,哪个日子在后。
# mysql
select a.visited_on,sum(c.amount) amount,round(sum(c.amount) / 7,2) average_amount
from (
select distinct visited_on
from customer c
where exists(
select 1
from customer
where datediff(c.visited_on,visited_on)=6
)
) a
inner join customer c on datediff(a.visited_on,c.visited_on)<=6 and datediff(a.visited_on,c.visited_on) >= 0
group by a.visited_on
order by a.visited_on
# mssql
select a.visited_on,sum(c.amount) amount,convert(decimal(16,2),sum(c.amount) * 1.0 / 7) average_amount
from (
select distinct visited_on
from customer c
where exists(
select 1
from customer
where datediff(d,visited_on,c.visited_on)=6
)
) a
inner join customer c on datediff(d,c.visited_on,a.visited_on)<=6 and datediff(d,c.visited_on,a.visited_on) >= 0
group by a.visited_on
order by a.visited_on
# oracle
select to_char(a.visited_on,'YYYY-mm-DD') visited_on,sum(c.amount) amount,round(sum(c.amount) * 1.0 / 7,2) average_amount
from (
select distinct visited_on
from customer c
where exists(
select 1
from customer
where c.visited_on - visited_on = 6
)
) a
inner join customer c on c.visited_on between a.visited_on - 6 and a.visited_on
group by a.visited_on
order by a.visited_on
https://leetcode.cn/problems/list-the-products-ordered-in-a-period/
嗯,日期范围,可以用 between 来描述,这样就可以一拖三了。至于不少于100的销售量,用having聚合筛选一下就好。
select p.product_name,sum(o.unit) unit
from products p
inner join orders o on p.product_id=o.product_id
where o.order_date between '2020-2-1' and '2020-2-29'
group by p.product_name
having(sum(o.unit)>=100)
https://leetcode.cn/problems/movie-rating/
额。完全两个不同的查询条件,聚合方式,然后得到两个结果集,放到一起输出。。。这个考的内容,不具有通用性。。。。算了,随便写写吧。
嗯,下边的内容,并不是某数据只能使用这一种方式,而是,在不同的数据里,用不同的方式进行实现了,小伙伴们也可以用任意数据库按照特定方式去实现查询结果。
# mysql
select *
from (
select name results
from movierating m
inner join users u on m.user_id=u.user_id
group by name
order by count(0) desc,name
limit 0,1
) a
union all
select *
from (
select title results
from movierating r
inner join movies m on r.movie_id=m.movie_id
where created_at between '2020-2-1' and '2020-2-29'
group by title
order by avg(rating) desc,title
limit 0,1
) b
# oracle
select *
from (
select u.name results
from movierating m
inner join users u on m.user_id=u.user_id
group by name
order by count(0) desc,name
) a
where rownum=1
union all
select *
from (
select m.title results
from movierating r
inner join movies m on r.movie_id=m.movie_id
where r.created_at between '2020-2-1' and '2020-2-29'
group by title
order by avg(r.rating) desc,title
) b
where rownum=1
# 一拖三,除了 mssql, * 1.0 都可以省略
select a.name results
from (
select a.*,row_number() over(partition by tp order by cnt desc,name) nid
from (
select u.name,sum(1) over(partition by u.user_id order by r.created_at) cnt,'1' tp
from users u
inner join MovieRating r on u.user_id=r.user_id
union all
select m.title,avg(rating * 1.0),'2' tp
from Movies m
inner join MovieRating r on m.movie_id=r.movie_id
where created_at >= '2020-2-1' and created_at < '2020-3-1'
group by title
) a
) a
where a.nid=1
https://leetcode.cn/problems/replace-employee-id-with-the-unique-identifier/
啊哦,又考回到 left join 了,完全没什么其他想法啊。
select u.unique_id,e.name
from Employees e
left join EmployeeUNI u on e.id=u.id
https://leetcode.cn/problems/capital-gainloss/
嗯?这个题目居然被定为中等难度?没看出来啊,不还是 group 和 sum 的问题吗?哦,难道一个 case when 就算一个难度了?
# 一拖三
select a.stock_name,sum(p) capital_gain_loss
from (
select s.*,(case when operation = 'Buy' then -price else price end) p
from stocks s
) a
group by a.stock_name
https://leetcode.cn/problems/top-travellers/submissions/
额。。。还是 left join 一个聚合结果。。。
# oracle
select a.name,nvl(b.d,0) as travelled_distance
from users a
left join (
select user_id,sum(distance) d
from rides
group by user_id
) b on a.id=b.user_id
order by nvl(b.d,0) desc,a.name
# mssql
select name,isnull(d,0) travelled_distance
from users a
left join (
select user_id,sum(distance) d
from rides
group by user_id
) b on a.id=b.user_id
order by d desc,name
# mysql
select name,ifnull(sum(distance),0) travelled_distance
from users a
left join rides r on r.user_id=a.id
group by a.id
order by travelled_distance desc,name
https://leetcode.cn/problems/group-sold-products-by-the-date/
哦,终于用到 group_concat 或 for xml 了,可惜老顾对 oracle 不熟悉,不知道怎么在 oracle 里搞出这个结果
# mysql
select sell_date,count(distinct product) num_sold,group_concat(distinct product order by product) products
from Activities
group by sell_date
order by sell_date
# mssql
select distinct sell_date,len(products) - len(replace(products,',','')) + 1 num_sold,products
from Activities a
cross apply (
select stuff((
select distinct ',' + product
from Activities
where sell_date=a.sell_date
order by ',' + product
for xml path('')
),1,1,'') products
) b
order by sell_date
https://leetcode.cn/problems/find-users-with-valid-e-mails/
额。。。。这个题目,有官方正则支持的,很容易,而 mssql 因为没有官方正则支持。。。只能验字符串了。。。。还好 tsql 的 like 也有类似的正则用法,虽然并不是完整的正则。
# mysql
select *
from Users
where mail regexp '^[a-zA-Z][a-zA-Z0-9_\.-]*@leetcode[\.]com$'
# oracle
select *
from Users
where regexp_like(mail,'^[a-zA-Z][a-zA-Z0-9_\.-]*@leetcode[\.]com$')
# mssql
select *
from users
where mail like '[a-zA-Z]%@leetcode.com'
and substring(mail,0,len(mail) - 12) not like '%[^a-zA-Z0-9_.-]%'
https://leetcode.cn/problems/patients-with-a-condition/
嗯嗯。这个题目,还是正则比 like 好用,尤其是 like 需要 or 的时候,效率太低了。
# mssql
select *
from patients
where ',' + replace(conditions,' ',',') like '%,diab1%'
# mysql
select *
from Patients
where conditions regexp '(?
# oracle
select *
from Patients
where regexp_like(conditions,'(^| )DIAB1')
额,这次10个题目,算是考的比较全面了,尤其是分组字符串合并,是一个很常用的内容,然后,就是正则这种匹配,也算是很常用的内容了。
但是,在没有正则的情况下,对于确定的字符串内容,其实我们还是有变动的办法的,嗯,这次有两个题目就是用 like 进行变通得到正确结果的。
所以说,一定要了解清楚,到底每个指令,都有哪些功能,能进行怎样的操作。
所有华丽的招式,都是有基础的动作构成的,只有了解了所有的基础内容,才能无招胜有招的完成所有需求。