where節に集計関数の条件を記述するとエラーになる - SQL

SQLのwhereに集計関数を記述するとエラーになる場合の対処方法を紹介します。

概要

SQLのwhere節に集計関数を用いた条件式を記述すると、実行時に下記のエラー「集計が HAVING 句または選択リスト内のサブクエリにある場合、および集計する列が外部参照の場合にだけ、WHERE 句に集計を含めることができます。」が発生します。

エラーメッセージ

メッセージ 147、レベル 15、状態 1、行 n 集計が HAVING 句または選択リスト内のサブクエリにある場合、および集計する列が外部参照の場合にだけ、WHERE 句に集計を含めることができます。 Server: Msg 147, Level 15, State 1, Line n An aggregate may not appear in the WHERE clause unless it is in a subquery contained in a HAVING clause or a select list, and the column being aggregated is an outer reference.

原因

whereの条件がgruop byの実行前に判定されるため、正しく実行できない可能性があります。

以下のテーブルの場合
ProductsA テーブル
idnamepricecategory
1Penguin250Bird
2Bear1050Mammal
3Duck150Bird
4Camel550Mammal
5Owl185Bird
6Whale880Mammal


このとき、下記のSQLを実行するとエラーになります。
select category, avg(price)as average from ProductsA where avg(price) > 500 group by category
avg()による平均値の算出は、group byの処理後に実行されますが、wheweの条件式はgroup by の処理前に実行されるため、avg()の平均値の算出ができないため実行エラーになります。

対策

havingを利用する

having句を利用すると、group byでの集計(グループ化)が終わった後で条件を指定できます。
先のエラーのコードは以下のコードにすると実行できます。
select category, avg(price)as average from ProductsA group by category having avg(price) > 500
having句の利用は「group by での集計結果に対して条件を指定して絞り込む - having の利用」の記事も参照してください。

結果

categoryaverage
1Mammal826.666666

サブクエリにする

あまり美しくはないですが、group byでの集計SQLをサブクエリにして、メインのクエリでwhereで条件指定する方法でも実行できます。
select * from (
  select category, avg(price)as average from ProductsA group by category )as A
where average > 500

著者
iPentec.com の代表。ハードウェア、サーバー投資、管理などを担当。
Office 365やデータベースの記事なども担当。
最終更新日: 2022-06-03
作成日: 2014-11-09
iPentec all rights reserverd.