PostgreSQL Where count condition

房东的猫 提交于 2019-11-27 14:34:39
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)

Major points

  • In versions prior to PostgreSQL 9.1 you have to add limit_call to the GROUP BY clause. Beginning with version 9.1 it is enough to have the primary key in the GROUP BY clause. The release notes for 9.1:

    Allow non-GROUP BY columns in the query target list when the primary key is specified in the GROUP BY clause

  • Your WHERE condition has to move to the HAVING clause since it refers to the result of an aggregate function. And you cannot refer to output columns (column aliases) in the HAVING clause, where you can only reference input columns. So you have to repeat the expression. Per documentation:

    An output column's name can be used to refer to the column's value in ORDER BY and GROUP BY clauses, but not in the WHERE or HAVING clauses; there you must write out the expression instead.

  • I reversed the order of tables in the FROM clause and cleaned up the syntax a bit to make it less confusing. USING is just a notational convenience here.

  • I used LEFT JOIN instead of JOIN, so you do not exclude licenses without any logs at all.

  • I would advise not to use mixed case identifiers in Postgres if possible. Very error prone.

  • Only non-null values are counted by count(). Since you want to count related entries in table "Log" it is safer and slightly cheaper to use count(b.license_id). This column is used in the join, so we don't have to bother whether the column can be null or not.
    count(*) is even shorter and slightly faster, yet. If you don't mind to get a count of 1 for 0 rows in the left table, use that.

The where query doesn't recognize your column alias, and furthermore, you're trying to filter out rows after aggregation. Try:

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

The having clause is similar to the where clause, except that it deals with columns after an aggregation, whereas the where clause works on columns before an aggregation.

Also, is there a reason why your table names are enclosed in double quotes?

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!