是否可以在windows函数中进行行级计算?

问题描述 投票:0回答:1

我正在 LeetCode.com 上解决这个问题:

列名称 类型
机器_id int
进程id int
活动类型 枚举
时间戳 漂浮

该表显示了工厂网站的用户活动。 (machine_id、process_id、activity_type) 是该表的主键(具有唯一值的列的组合)。 machine_id 是机器的 ID。 process_id 是在 ID 为 machine_id 的计算机上运行的进程的 ID。 Activity_type 是类型为 ('start', 'end') 的 ENUM(类别)。 时间戳是一个浮点数,表示当前时间(以秒为单位)。 “start”表示机器在给定时间戳开始进程,“end”表示机器在给定时间戳结束进程。 对于每个(machine_id,process_id)对,“开始”时间戳始终位于“结束”时间戳之前。

有一个工厂网站,有几台机器,每台机器都运行相同数量的进程。编写一个解决方案来找出每台机器完成一个过程所需的平均时间。

完成一个过程的时间是“结束”时间戳减去“开始”时间戳。平均时间的计算方法是:完成机器上每个进程的总时间除以已运行的进程数。

结果表应包含 machine_id 以及平均时间作为processing_time,应四舍五入到小数点后 3 位。

以任意顺序返回结果表。

我能够使用自连接解决这个问题,但我发现最佳实践是避免自连接,而是使用窗口函数但是,我不知道该怎么做(如果可能的话)。

我可以通过如下自连接解决问题:

select a1.machine_id, round(avg(a2.timestamp-a1.timestamp), 3) as processing_time 
from Activity a1
join Activity a2 
on a1.machine_id=a2.machine_id and a1.process_id=a2.process_id
and a1.activity_type='start' and a2.activity_type='end'
group by a1.machine_id

我还可以启动这样的窗口函数:

SELECT a1.machine_id, AVG(a1.timestamp) OVER (PARTITION BY machine_id) AS processing_time
FROM Activity AS a1

但是是否可以在聚合这些平均值时进行行级计算来减去时间? 另外,当我将 group by a1.machine_id 添加到底部时,我的上述代码(第二块)不起作用。 任何人都可以解释为什么吗?这是具体的错误:

[42000] [Microsoft][SQL Server 的 ODBC 驱动程序 17][SQL Server]列“Activity.timestamp”在选择列表中无效,因为它未包含在聚合函数或 GROUP BY 子句中。 (8120) (SQLExecDirectW)

sql sql-server window-functions self-join coding-efficiency
1个回答
0
投票

窗口函数有点棘手,因为您想要的平均窗口将无法实现,因为您需要差异

您可以使用 LAG 或 LEAD 获取最后一行或下一行进行减法

CREATE TABLe Activity  (machine_id int ,
process_id  int,
activity_type   VARCHAR(10) NOT NULL CHECK (activity_type IN('begin', 'end')),
timestamp   float)
INSERT INTO Activity  VALUES(1,1,'Begin', 1.2),(1,1,'End', 2.2),(1,2,'Begin', 3.2),(1,2,'End', 5.2)
WITH CTE AS (SELECT a1.machine_id, process_id 
 , 
 CASE WHEN  activity_type = 'end' Then a1.timestamp 
  -  LAG(a1.timestamp) OVER (PARTITION BY machine_id,process_id ORDER BY activity_type ) END
   processing_time
FROM Activity AS a1)
  SELECT machine_id,
  AVG(processing_time) as processing_time 
  FROM CTE
WHERE processing_time IS NOT NULL
  GROUP BY machine_id
机器_id 处理时间
1 1.5
select a1.machine_id, round(avg(a2.timestamp-a1.timestamp), 3) as processing_time 
from Activity a1
join Activity a2 
on a1.machine_id=a2.machine_id and a1.process_id=a2.process_id
and a1.activity_type='start' and a2.activity_type='end'
group by a1.machine_id

机器_id 处理时间

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.