web-dev-qa-db-ja.com

PostgreSQL Whereカウント条件

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)

特定の月にライセンスが通話の制限に達したかどうかを確認したい。

33
Hadi
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_callGROUP 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のカウントを取得することを気にしない場合は、それを使用します。

46

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句は集約前の列で動作します。

また、テーブル名が二重引用符で囲まれている理由はありますか?

6
user554546