You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL如何计算指定行求和后的平均值

解决思路与修正后的SQL

你的问题核心是没有先按日期聚合每日的有效劳动时长,就直接对单条记录的duration求平均,这和需求里“先每日求和,再求日总和的平均值”不符。我们可以分两步来实现:


第一步:计算每个用户每日的有效劳动时长总和

先把日志按用户和日期分组,筛选掉休息类状态,计算当天所有有效状态的duration总和:

SELECT
  login,
  DATE(started_at) AS work_date,
  SUM(duration) FILTER (WHERE state NOT IN ('lunch', 'break1', 'break2')) AS daily_labor_total
FROM log
GROUP BY login, DATE(started_at)

这一步会得到每个用户每天的有效劳动时长总和,比如pdiddy在2018-05-25的总和就是1200 + 65 + 1115 + 143 + 2400(排除了lunch、break1、break2的记录)。

第二步:对每日总和求平均值

基于上面的结果,再按用户分组,对daily_labor_total求平均就是最终需要的劳动时长平均值:

SELECT
  login,
  AVG(daily_labor_total) AS labor_average
FROM (
  SELECT
    login,
    DATE(started_at) AS work_date,
    SUM(duration) FILTER (WHERE state NOT IN ('lunch', 'break1', 'break2')) AS daily_labor_total
  FROM log
  GROUP BY login, DATE(started_at)
) AS daily_totals
GROUP BY login

用CTE(公共表表达式)优化可读性

如果你觉得子查询有点绕,也可以用CTE来拆分逻辑,可读性更强:

WITH daily_labor_totals AS (
  SELECT
    login,
    DATE(started_at) AS work_date,
    SUM(duration) FILTER (WHERE state NOT IN ('lunch', 'break1', 'break2')) AS daily_total
  FROM log
  GROUP BY login, DATE(started_at)
)
SELECT
  login,
  AVG(daily_total) AS labor_average
FROM daily_labor_totals
GROUP BY login

这样就完全符合你的需求了:先按天汇总有效时长,再计算这些日汇总值的平均值。

内容的提问来源于stack exchange,提问作者Luke Visinoni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:16:20