5

ログ データを保持する 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]

ここでのクエリは、1 日の時間ごとの訪問数の分布を見つけることに関するものです。特定の日付範囲における 1 時間の平均訪問数の分布を確認したいと考えています。訪問サンプル

クエリの結果は次のようになります。

HourOfDay Avg.Visits.In.Hour
0 24
1 16
5 32
6 89
7 823
などなど

意図は、次のようなクエリを書くことです:

SELECT  DATEPART(hh, VisitDate)
        ,AVG(COUNT(*))    
FROM    CustomerLog
WHERE   VisitDate   BETWEEN 'Jan 1 2009' AND 'Aug 1 2009'
GROUP BY   DATEPART(hh, VisitDate)

ただし、これは有効なクエリではありません。

集計またはサブクエリを含む式に対して集計関数を実行することはできません。

質問:平均合計を収集するには、このクエリをどのように書き直しますか (つまりAVG(COUNT(*))、1 時間の代わりに?

このクエリの結果が、1 日の最も忙しい時間を知りたいPHBに渡されると想像してください。

  • SQL Server 2005 以降
4

2 に答える 2

7

インラインビューの使用:

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)
于 2009-11-13T18:56:38.903 に答える
0

日数は既知であり、 に等しくなり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)

CAST(COUNT(*) AS FLOAT)より正確な結果が得られますが、そのままにCOUNT(*)して整数の結果を得ることができます。

パラメータを使用すると、次のようになります。

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)

1 月の結果が必要な場合は、@beginningDate = '2009.01.01', @endDate = '2009.02.01' を使用する必要があります。

于 2009-11-13T21:22:36.147 に答える