PostgreSQLには次のクエリがあります。
SELECT
COUNT(a.log_id) AS overall_count
FROM
"Log" as a,
"License" as b
WHERE
a.license_id=7
AND
a.license_id=b.license_id
AND
b.limit_call > overall_count
GROUP BY
a.license_id;
なぜこのエラーが発生するのですか:
エラー:列「overall_count」は存在しません
私のテーブル構造:
License(license_id, license_name, limit_call, create_date, expire_date)
Log(log_id, license_id, log, call_date)
特定の月にライセンスが通話の制限に達したかどうかを確認したい。
SELECT a.license_id, a.limit_call
, count(b.license_id) AS overall_count
FROM "License" a
LEFT JOIN "Log" b USING (license_id)
WHERE a.license_id = 7
GROUP BY a.license_id -- , a.limit_call -- add in old versions
HAVING a.limit_call > count(b.license_id)
PostgreSQL 9.1より前のバージョンでは、limit_call
をGROUP BY
句に追加する必要があります。バージョン9.1以降では、GROUP BY
句に主キーがあれば十分です。 9.1のリリースノート :
プライマリキーが
GROUP BY
句で指定されている場合、クエリターゲットリストでnon_GROUP BY
列を許可します
WHERE
条件は、集約関数の結果を参照するため、HAVING
句に移動する必要があります。また、HAVING
句でoutput columns(列エイリアス)を参照することはできません。入力列のみを参照できます。そのため、式を繰り返す必要があります。 ドキュメントごと:
出力列の名前は、
ORDER BY
句とGROUP BY
句で列の値を参照するために使用できますが、WHERE
句またはHAVING
句では使用できません。そこで、代わりに式を書き出す必要があります。
FROM
節のテーブルの順序を逆にし、構文を少し整理して、混乱を少なくしました。 USING
は、ここでは単なる表記上の便宜です。
JOIN
の代わりにLEFT JOIN
を使用したため、ログのないライセンスをまったく除外しません。
not を使用して、可能であればPostgresで mixed case identifiers を使用することをお勧めします。非常にエラーが発生しやすい。
NULL以外の値のみがcount()
によってカウントされます。テーブル"Log"
の関連エントリをカウントしたいので、count(b.license_id)
を使用する方が安全でわずかに安価です。この列は結合で使用されるため、列をnullにできるかどうかを気にする必要はありません。count(*)
はさらに短く、わずかに高速です。左のテーブルの1
行の0
のカウントを取得することを気にしない場合は、それを使用します。
where
クエリは列のエイリアスを認識せず、さらに、行を除外しようとしていますafter集計。試してください:
SELECT
COUNT(a.log_id) AS overall_count
FROM
"Log" as a,
"License" as b
WHERE
a.license_id=7
AND
a.license_id=b.license_id
GROUP BY
a.license_id
having b.limit_call > count(a.log_id);
having
句はwhere
句に似ていますが、集約後の列を処理するのに対して、where
句は集約前の列で動作します。
また、テーブル名が二重引用符で囲まれている理由はありますか?