Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HAVING clause in PostgreSQL

Tags:

postgresql

I'm rewriting the MySQL queries to PostgreSQL. I have table with articles and another table with categories. I need to select all categories, which has at least 1 article:

SELECT c.*,(
    SELECT COUNT(*) 
    FROM articles a 
    WHERE a."active"=TRUE AND a."category_id"=c."id") "count_articles" 
FROM articles_categories c 
HAVING (
    SELECT COUNT(*) 
    FROM articles a 
    WHERE a."active"=TRUE AND a."category_id"=c."id" ) > 0

I don't know why, but this query is causing an error:

ERROR:  column "c.id" must appear in the GROUP BY clause or be used in an aggregate function at character 8
like image 753
Radek Simko Avatar asked Mar 31 '11 07:03

Radek Simko


People also ask

What is HAVING clause used for?

To complement a GROUP BY clause, use a HAVING clause to apply one or more qualifying conditions to groups after they are formed. The effect of the HAVING clause on groups is similar to the way the WHERE clause qualifies individual rows.

What is difference between HAVING and WHERE clause?

What is the Difference between Where and Having Clause in SQL? If “Where” clause is used to filter the records from a table that is based on a specified condition, then the “Having” clause is used to filter the record from the groups based on the specified condition.

What is the difference between HAVING and WHERE in PostgreSQL?

The WHERE clause allows you to filter rows based on a specified condition. However, the HAVING clause allows you to filter groups of rows according to a specified condition. In other words, the WHERE clause is applied to rows while the HAVING clause is applied to groups of rows.

What is HAVING and GROUP BY clause?

The HAVING clause is used instead of WHERE with aggregate functions. While the GROUP BY Clause groups rows that have the same values into summary rows. The having clause is used with the where clause in order to find rows with certain conditions. The having clause is always used after the group By clause.


1 Answers

The HAVING clause is a bit tricky to understand. I'm not sure about how MySQL interprets it. But the Postgres documentation can be found here:

http://www.postgresql.org/docs/9.0/static/sql-select.html#SQL-HAVING

It essentially says:

The presence of HAVING turns a query into a grouped query even if there is no GROUP BY clause. This is the same as what happens when the query contains aggregate functions but no GROUP BY clause. All the selected rows are considered to form a single group, and the SELECT list and HAVING clause can only reference table columns from within aggregate functions. Such a query will emit a single row if the HAVING condition is true, zero rows if it is not true.

The same is also explained in this blog post, which shows how HAVING without GROUP BY implicitly implies a SQL:1999 standard "grand total", i.e. a GROUP BY ( ) clause (which isn't supported in PostgreSQL)

Since you don't seem to want a single row, the HAVING clause might not be the best choice.

Considering your actual query and your requirement, just rewrite the whole thing and JOIN articles_categories to articles:

SELECT DISTINCT c.*
FROM articles_categories c
JOIN articles a 
ON a.active = TRUE 
AND a.category_id = c.id

alternative:

SELECT *
FROM articles_categories c
WHERE EXISTS (SELECT 1 
                FROM articles a
               WHERE a.active = TRUE 
                 AND a.category_id = c.id)
like image 51
Lukas Eder Avatar answered Oct 21 '22 07:10

Lukas Eder