2011-03-31 15 views
5

Estoy reescribiendo las consultas MySQL a PostgreSQL. Tengo una tabla con artículos y otra tabla con categorías. Necesito seleccionar todas las categorías, que tiene al menos 1 artículo:cláusula HAVING en PostgreSQL

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 

No sé por qué, pero esta consulta está causando un error:

ERROR: column "c.id" must appear in the GROUP BY clause or be used in an aggregate function at character 8 

Respuesta

11

La cláusula HAVING es un poco complicado comprender. No estoy seguro de cómo MySQL lo interpreta. Sin embargo, la documentación de Postgres se puede encontrar aquí:

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

Esencialmente dice:

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, que muestra cómo HAVING sin GROUP BY implica implícitamente un estándar SQL: 1999 "total", es decir, una cláusula GROUP BY () (que no se admite en PostgreSQL)

Dado que no parece querer una fila única , la cláusula HAVING podría no ser la mejor opción.

Teniendo en cuenta su consulta real y su requerimiento, simplemente volver a escribir todo el asunto y JOINarticles_categories-articles:

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

alternativa:

SELECT * 
FROM articles_categories c 
WHERE EXISTS (SELECT 1 
       FROM articles a 
       WHERE a.active = TRUE 
       AND a.category_id = c.id) 
+0

Pero este resultado debe ser agrupado De todos modos o tengo que usar DISTINCT(), ¿no? –

+0

Sí, por supuesto. Lo siento ... Corregí la consulta y proporcioné una alternativa –

+0

'HAVING' sin' GROUP BY' es legal en SQL y también es compatible con PostgreSQL. Esto no tiene nada que ver con el problema. –

0
select * from categories c 
where 
exists (select 1 from article a where c.id = a.category_id); 

debe estar bien ... quizá más sencillo ;)