【力扣白嫖日记】SQL
前言
练习sql语句,所有题目来自于力扣(https://leetcode.cn/problemset/database/)的免费数据库练习题。
今日题目:
1661.每台机器的进程平均运行时间
表:Activity
列名 | 类型 |
---|---|
machine_id | int |
process_id | int |
activity_type | enum |
timestamp | float |
该表展示了一家工厂网站的用户活动。
- (machine_id, process_id, activity_type) 是当前表的主键(具有唯一值的列的组合)。machine_id 是一台机器的ID号。process_id 是运行在各机器上的进程ID号。
- activity_type 是枚举类型 (‘start’, ‘end’)。
- timestamp 是浮点类型,代表当前时间(以秒为单位)。
- ‘start’ 代表该进程在这台机器上的开始运行时间戳 , ‘end’ 代表该进程在这台机器上的终止运行时间戳。同一台机器,同一个进程都有一对开始时间戳和结束时间戳,而且开始时间戳永远在结束时间戳前面。
现在有一个工厂网站由几台机器运行,每台机器上运行着 相同数量的进程 。编写解决方案,计算每台机器各自完成一个进程任务的平均耗时。
完成一个进程任务的时间指进程的’end’ 时间戳 减去 ‘start’ 时间戳。平均耗时通过计算每台机器上所有进程任务的总耗费时间除以机器上的总进程数量获得。
结果表必须包含machine_id(机器ID) 和对应的 average time(平均耗时) 别名 processing_time,且四舍五入保留3位小数。
以 任意顺序 返回表。
我那不值一提的想法:
- 首先梳理表内容,题干给了一张活动表,记录了一台机器的id,进程id,活动类型有开始和结束,时间戳。
- 其次分析需求,需要得到每台机器上完成一个任务的平均耗时。
- 我认为,首先要确定这个平均耗时的定义,也就是如何计算。也就是每台机器,每个进程从开始到结束状态,之间的时间戳的差,再除以进程数量。基本公式就是(结束时间戳-开始时间戳)/进程数量。
- 那么我们该如何表示每台机器的每个进程的平均用时呢,每台机器也就是
group by machine_id
,每个进程也就是group by process_id
,每台机器,每个进程也就是group by machine_id,process_id
。 - 每台机器的每个进程的问题解决了,那结束和开始怎么表示呢,我的第一个想法就是max和min,既然分开始和结束那么结束的时间一定最大,开始的时间一定最小,直接用
(max(timestamp)-min(timestamp))
那么代码如下:
select machine_id,max(timestamp)-min(timestamp)/count(distinct process_id)as processing_time
from Activity
group by machine_id,process_id
结果出现差错,但可以看到我们的结果只和答案差了一个求和然后取小数点后三位。于是我就想当然的直接加sum,也就是这样:sum(max(timestamp)-min(timestamp)/count(distinct process_id))
,但是这样的语法是错误的,数据库识别不到timestamp,因为在group by 里面没有timestamp。所以这样不行。于是到这里我就卡住了,后来我想,既然数据库不行,那么我可以直接把我这个的搜索结果当成一个临时表a,从临时表a里面聚合然后求和得到我们的结果,也就是这样:
select a.machine_id,round(sum(a.processing_time)/count(a.processing_time),3) as processing_time
from
(select machine_id,max(timestamp)-min(timestamp)/count(distinct process_id) as processing_time
from Activity
group by machine_id,process_id
) as a
group by machine_id
这样就能得出我们的正确结果了。
结果:
总结:
能运行就行。