【问题标题】:Calculating the AVG value per GROUP in the GROUP BY Clause在 GROUP BY 子句中计算每个 GROUP 的 AVG 值
【发布时间】:2016-01-03 17:39:28
【问题描述】:

我正在 SQL Server 2005 中进行查询,该查询查看记录的电话呼叫表,按一天中的时间对它们进行分组,并计算一天中每个小时的平均等待时间。

我有一个我认为可行的查询,但我无法说服自己它是正确的。

SELECT
    DATEPART(HOUR, CallTime) AS Hour,
    (AVG(calls.WaitDuration) / 60) AS WaitingTimesInMinutes
FROM (
    SELECT
        CallTime,
        WaitDuration
    FROM Calls
    WHERE DATEADD(day, DATEDIFF(Day, 0, CallTime), 0) = DATEADD(day, DATEDIFF(Day, 0, GETDATE()), 0)
        AND DATEPART(HOUR, CallTime) BETWEEN 6 AND 18
) AS calls
GROUP BY DATEPART(HOUR, CallTime)
ORDER BY DATEPART(HOUR, CallTime);

为了澄清我认为正在发生的事情,此查询会查看与今天在同一天拨打的所有电话,以及通话时间在 6 到 18 点之间的时间 - 时间是按 24 小时时间记录和选择的,所以这几个小时之间是在早上 6 点到下午 6 点之间接听电话。

然后,外部查询计算 WaitDuration 列的平均值(并将秒转换为分钟),然后按小时对每个平均值进行分组。

我不确定的是:按小时报告的平均值是否仅针对在该小时的时间范围内拨打的电话?或者它是否使用当天和几个小时之间的所有呼叫来计算每个报告的平均值?我知道 AVG 函数有一个可选的 OVER/PARTITION 子句,而且我已经有一段时间没有使用 AVG 组函数了。我想要的是按小时分组的每个结果仅显示一天中特定小时的平均等待时间。

感谢您抽出宝贵时间。

【问题讨论】:

  • 您对工作时间的限制实际上是允许在下午 6:59:59 之前拨打电话。您可能应该直接说 CallTime BETWEEN <start> and <end> 或至少在 17 小时停止。
  • 哦,很好,@Shawn!谢谢。
  • CallTime >= dateadd(hour, 6, cast(current_timestamp as date))) and CallTime < dateadd(hour, 18, cast(current_timestamp as date)))
  • 我将采用第一个想法,因为 SQL Server 2005 没有 DATE 类型。 :)
  • 我不记得他们是在 2005 年还是 2008 年添加的。您可以随时使用{fn current_date()}

标签: sql sql-server-2005 group-by average


【解决方案1】:

分组发生在从datepart(hour, ...) 吐出的值上。您已经在对该值进行过滤,因此您知道它们的范围在 6 到 18 之间。这就是分组将看到的全部内容。

现在datepart() 函数当然可以满足您的需求,因为它查看时钟并给出时间的小时部分。如果您希望您的组与 HH:00:00 到 HH:59:59.997 相吻合,那么您很幸运。

我已经在 cmets 中指出,您可能打算过滤从 6 到 17 的范围,如果您更改它并将原始 CallTime 值与静态范围进行比较,您的查询可能会执行得更好。你的推理在我看来是正确的。而且因为您的推理是正确的,所以您根本不需要内部查询(派生表)。

此外,如果WaitDuration 是一个整数,那么您将在输出中进行十进制除法。在这种情况下,您需要转换为十进制或将除数更改为十进制值,例如 60.00。

【讨论】:

  • 我将此标记为正确答案,因为它提供了有关我的查询的最多信息,帮助我了解查询的正确性。因此,我认为它最能回答我的问题。
【解决方案2】:

是的,如果您将 AVG 函数与 GROUP BY 一起使用,则仅对该组中的项目进行平均。就像如果您将 COUNT 函数与 GROUP BY 一起使用,则仅计算该组中的项目。

您可以使用窗口函数(OVER/PARTITION)在概念上根据单个函数的不同条件执行 GROUP BY。

例如

AVG(zed) OVER (PARTITION BY DATEPART(YEAR, CallTime)) as YEAR_AVG

【讨论】:

  • 这个答案我也觉得很有用而且很清楚。谢谢@Hogan!
【解决方案3】:

按小时报告的平均值是否仅针对在该小时的时间范围内拨打的电话?

是的。 WHERE 子句应用于分组和聚合之前,因此聚合将应用于符合WHERE 子句和每个组内的所有记录。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-26
    • 1970-01-01
    • 2012-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多