49

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)

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

4

3 に答える 3

59
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)

Postgres 9.1 以降、主キーはGROUP BY句内のテーブルのすべての列をカバーします。古いバージョンではa.limit_callGROUP BYリストに追加する必要があります。9.1のリリース ノート:

GROUP BYで主キーが指定されている場合、クエリ対象リストで列以外を許可するGROUP BY

参考文献:

句に含まれていた条件は、集計関数の結果を参照しているため (適用WHERE) 、句に移動する必要があります。また、入力列のみを参照できる節では、出力列(列の別名) を参照できません。したがって、式を繰り返す必要があります。マニュアル:HAVING WHEREHAVING

出力列の名前は、 ORDER BYandGROUP BY句で列の値を参照するために使用できますが、WHEREorHAVING 句では使用できません。代わりに式を書き出す必要があります。

節内のテーブルの順序を逆にFROMし、構文を少しクリーンアップして混乱を減らしました。USINGここでは便宜上の表記にすぎません。

LEFT JOINの代わりに使用したJOINため、ログのないライセンスは除外されません。

によってカウントされるのは、null 以外の値のみcount()です。テーブル内の関連するエントリをカウントしたいので、"Log"より安全で、使用する方がわずかに安価count(b.license_id)です。この列は結合で使用されるため、列が null になるかどうかを気にする必要はありません。
count(*)はさらに短く、わずかに高速です。左のテーブルの行のカウントを取得しても構わない場合は、それを使用して1ください。0

余談ですが、可能であれば、Postgres で大文字と小文字が混在する識別子を使用しないことをお勧めします。非常にエラーが発生しやすい。

于 2011-11-14T09:54:02.170 に答える
10

クエリは列のwhereエイリアスを認識せず、さらに集計後に行を除外しようとしています。試す:

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、句と似ていますが、句は集計前の列に対して機能します。wherewhere

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

于 2011-11-14T09:32:33.313 に答える