TSQL:无法对计数(*)执行聚合函数AVG以查找一天中最忙的小时数

TSQL:无法对计数(*)执行聚合函数AVG以查找一天中最忙的小时数,sql,sql-server,sql-server-2005,tsql,aggregate-functions,Sql,Sql Server,Sql Server 2005,Tsql,Aggregate Functions,考虑一个包含日志数据的SQL Server表。重要的部分是: CREATE TABLE [dbo].[CustomerLog]( [ID] [int] IDENTITY(1,1) NOT NULL, [CustID] [int] NOT NULL, [VisitDate] [datetime] NOT NULL, CONSTRAINT [PK_CustomerLog] PRIMARY KEY CLUSTERED ([ID] ASC)) ON [PRIMARY] 这里的

考虑一个包含日志数据的SQL Server表。重要的部分是:

CREATE TABLE [dbo].[CustomerLog](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [CustID] [int] NOT NULL,
    [VisitDate] [datetime] NOT NULL,
 CONSTRAINT [PK_CustomerLog] PRIMARY KEY CLUSTERED ([ID] ASC)) ON [PRIMARY]
这里的查询是按小时查找访问量的分布。我们感兴趣的是查看给定日期范围内小时的平均访问次数分布。

查询结果如下所示:

HourOfDay Avg.Visits.In.Hour 0 24 1 16 5 32 6 89 7 823 etc.etc. 但是,这不是有效的查询:

无法对包含聚合或子查询的表达式执行聚合函数

问题:您将如何重新编写此查询以收集该小时的平均总数(即代替
AVG(COUNT(*)

想象一下,这个查询的结果将被交给一个想知道一天中最忙的时间是什么的人

  • SQL Server 2005+
使用内联视图:

SELECT DATEPART(hh, x.visitdate),
       AVG(x.num)
  FROM (SELECT t.visitdate,
               COUNT(*) 'num'
          FROM CUSTOMERLOG t
         WHERE t.visitdate BETWEEN 'Jan 1 2009' AND 'Aug 1 2009'
      GROUP BY t.visitdate) x
GROUP BY DATEPART(hh, x.visitdate)
使用CTE(SQL Server 2005+)等效工具:

WITH visits AS (
   SELECT t.visitdate,
          COUNT(*) 'num'
     FROM CUSTOMERLOG t
    WHERE t.visitdate BETWEEN 'Jan 1 2009' AND 'Aug 1 2009'
 GROUP BY t.visitdate)
   SELECT DATEPART(hh, x.visitdate),
         AVG(x.num)
    FROM visits x
GROUP BY DATEPART(hh, x.visitdate)

天数已知,等于
DATEDIFF(day,CONVERT(DATETIME,'2009.01.01',120),CONVERT(DATETIME,'2009.09.01',120))
。 您必须计算总和并将其除以所选范围内的天数:

SELECT  
  DATEPART(hh, VisitDate),
  CAST(COUNT(*) AS FLOAT) / DATEDIFF(day,CONVERT(DATETIME,'2009.01.01',120),CONVERT(DATETIME,'2009.09.01',120))
FROM CustomerLog
WHERE 
  (VisitDate >= CONVERT(DATETIME,'2009.01.01',120)) AND 
  (VisitDate < CONVERT(DATETIME,'2009.09.01',120))  
GROUP BY DATEPART(hh, VisitDate)

如果你想要一月份的结果,你必须使用@beginningDate='2009.01.01',@endDate='2009.02.01.

你是说,比如说,在X个月的时间跨度内,上午10:00-11:00的平均访问次数?我读对了吗?@Matthew,是的!我会更新这个问题以反映所需的结果。一个警告-如果是在给定的一天内,为given hour没有访问,你想在平均值中反映出零吗?目前为止,这两种解决方案都没有涵盖this@OMG小马:在CTE版本中,您可能实际上希望将CTE中的
DATEPART(hh,x.visitdate)
返回为类似于
DATEPART(hh,x.visitdate)的visitour
,以便在CTE中只转换一次。
SELECT  
  DATEPART(hh, VisitDate),
  CAST(COUNT(*) AS FLOAT) / DATEDIFF(day,CONVERT(DATETIME,'2009.01.01',120),CONVERT(DATETIME,'2009.09.01',120))
FROM CustomerLog
WHERE 
  (VisitDate >= CONVERT(DATETIME,'2009.01.01',120)) AND 
  (VisitDate < CONVERT(DATETIME,'2009.09.01',120))  
GROUP BY DATEPART(hh, VisitDate)
SELECT  
  DATEPART(hh, VisitDate),
  CAST(COUNT(*) AS FLOAT) / DATEDIFF(day,@beginningDate,@endDate)
FROM CustomerLog
WHERE 
  (VisitDate >= @beginningDate) AND 
  (VisitDate < @endDate)  
GROUP BY DATEPART(hh, VisitDate)