【问题标题】:SQL Server: Average counts by hour and day of weekSQL Server:按小时和星期几的平均计数
【发布时间】:2012-05-06 17:59:51
【问题描述】:

背景

我在 SQL Server 环境中设置了一个表,其中包含我正在跟踪的各种活动的日志。特定日志项使用唯一代码对正在发生的活动进行分类,并使用日期时间字段跟踪该活动发生的时间。

问题

我想使用单个查询或存储过程来获得按星期几分组的平均每小时活动计数。示例:

Day      | Hour | Average Count
-------------------------------
Monday   | 8    | 5
Monday   | 9    | 5
Monday   | 10   | 9
...
Tuesday  | 8    | 4
Tuesday  | 9    | 3
...etc

现在,我有一个查询设置,可以输出每天每小时的计数,但我的问题是更进一步,并按一周中的每一天计算平均值。这是我当前的查询:

SELECT CAST([time] AS date) AS ForDate,
   DATEPART(hour, [time]) AS OnHour,
   COUNT(*) AS Totals
FROM [log] WHERE [code] = 'tib_imp.8'
GROUP BY CAST(time AS date),
   DATEPART(hour,[time])
   ORDER BY ForDate Asc, OnHour Asc

关于我如何实现这一点的任何建议?

提前致谢!

【问题讨论】:

  • weekday分组即可。
  • 这会平均计数吗?
  • 不,如果你想对计数进行平均,那么你必须先进行计数,然后对结果进行平均:select field, avg(countField) from ( select field, count(*) as countField group by field) result group by field
  • 如果您提供一些源数据(例如,您如何达到 5),我们将更好地了解您希望如何获得总计、平均值或总计的平均值。单词问题有点模棱两可,没有源数据很难确定 5,5,9 等的来源。

标签: sql sql-server count group-by


【解决方案1】:

在这里猜测:

SELECT [Day], [Hour], [DayN], AVG(Totals) AS [Avg]
FROM
  (
        SELECT 
          [Day]  = DATENAME(WEEKDAY, [time]),
          [DayN] = DATEPART(WEEKDAY, [time]),
          [Hour] = DATEPART(HOUR,    [time]),
          Totals = COUNT(*)
        FROM dbo.[log] 
            WHERE [code] = 'tib_imp.8'
        GROUP BY 
          DATENAME(WEEKDAY, [time]),
          DATEPART(WEEKDAY, [time]),
          DATEPART(HOUR,    [time])
  ) AS q
GROUP BY [Day], [Hour], [DayN]
ORDER BY DayN; 

再一次,如果没有数据,我可能会再次向墙上扔一把泥,希望它能粘住,但也许你需要的是:

SELECT [Day], [Hour], [DayN], AVG(Totals) AS [Avg]
FROM
(
    SELECT 
  w = DATEDIFF(WEEK, 0, [time]),
      [Day]  = DATENAME(WEEKDAY, [time]),
      [DayN] = DATEPART(WEEKDAY, [time]),
      [Hour] = DATEPART(HOUR,    [time]),
      Totals = COUNT(*)
    FROM dbo.[log] 
      WHERE [code] = 'tib_imp.8'
    GROUP BY 
  DATEDIFF(WEEK, 0, [time]),
      DATENAME(WEEKDAY, [time]),
      DATEPART(WEEKDAY, [time]),
      DATEPART(HOUR,    [time])
  ) AS q
GROUP BY [Day], [Hour], [DayN]
ORDER BY DayN; 

这也将产生基于整数的平均值,因此您可能希望将内部查询中的 Totals 别名转换为 DECIMAL(something,something)。

【讨论】:

  • @Siva 你是对的。本来我只有前两个,然后在测试的时候加了外层,最终不需要了。
  • @AaronBertrand 简洁优雅。很好的答案,按预期工作。很抱歉没有提供原始数据,其中有很多(我在问题中发布的数字是假的 - 因为我还没有达到平均水平。但最终,数据可能是随机的任何随机日志条目集过去几周的时间/天......如果这有意义的话。无论如何 - 非常感谢你!
  • @AaronBertrand 我以为我们有它(但一周后事实证明并非如此)......就返回的内容而言,内部和外部语句实际上没有区别.外部内部查询已经按星期几分组 - 因此只返回一个值/一天中的小时/星期几(不管我们是否正在检查多个星期)。所以外部查询只是对单个数字进行平均,这将始终与单个计数相同......这有意义吗?
  • @mbeasley 如所写,没有。请提供一些样本数据和期望的结果。我无法解决 T-SQL 中的单词问题,就像我上面所说的,我猜。但是,我可以解决数据问题。我在对这个问题的评论中要求这个 4 月 26 日。如果您提供我要求的内容,我将有更好的机会提供您需要的查询。如果问题发生了变化,也许值得提出一个新问题。
【解决方案2】:
; WITH a AS (
    SELECT CAST([time] AS date) AS ForDate
       , DATEPART(hour, [time]) AS OnHour
       , txtW=DATENAME(WEEKDAY,[time])
       , intW=DATEPART(WEEKDAY,[time])
       , Totals=COUNT(*)
    FROM [log] WHERE [code] = 'tib_imp.8'
    GROUP BY CAST(time AS date)
    , DATENAME(WEEKDAY,[time])
    , DATEPART(WEEKDAY,[time])
    , DATEPART(hour,[time])
)
SELECT [Day]=txtW
, [Hour]=OnHour
, [Average Count]=AVG(Totals)
FROM a
GROUP BY txtW, intW, OnHour
ORDER BY intW, OnHour

【讨论】:

  • John,尽管与此处的其他两个解决方案相比,您的执行计划有一个额外的排序运算符,但输出似乎没有正确排序(日期似乎是随机排序的)。
  • ORDER BY 修复了结果吗?
  • 不,现在它按工作日名称的字母顺序(周五、周一、周四、周二、周六、周日、周三)排序。
  • 那里,按需要排序。但是额外的排序仍然使该计划比其他两种解决方案(具有相同的计划)更昂贵。
  • 也许将函数调用放入 cte 有帮助
猜你喜欢
  • 2020-09-09
  • 2016-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多