PostgreSQL中的HAVING子句

Rad*_*mko 7 postgresql

我正在将MySQL查询重写为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
Run Code Online (Sandbox Code Playgroud)

我不知道为什么,但这个查询导致错误:

ERROR:  column "c.id" must appear in the GROUP BY clause or be used in an aggregate function at character 8
Run Code Online (Sandbox Code Playgroud)

Luk*_*der 13

HAVING条款有点难以理解.我不确定MySQL如何解释它.但Postgres文档可以在这里找到:

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

它基本上说:

即使没有GROUP BY子句,HAVING的存在也会将查询转换为分组查询.这与查询包含聚合函数但没有GROUP BY子句时发生的情况相同.所有选定的行都被视为组成一个组,SELECT列表和HAVING子句只能引用聚合函数中的表列.如果HAVING条件为真,则此类查询将发出单行,如果不为真,则为零行.

在这篇博客文章中也解释了同样的内容,它显示了如何在HAVING没有GROUP BY隐含地暗示SQL:1999标准"总计"的情况下,即一个GROUP BY ( )子句(PostgreSQL中不支持)

由于您似乎不想要单行,因此该HAVING子句可能不是最佳选择.

考虑到你的实际查询和您的要求,只是重写了整个事情,并JOIN articles_categoriesarticles:

SELECT DISTINCT c.*
FROM articles_categories c
JOIN articles a 
ON a.active = TRUE 
AND a.category_id = c.id
Run Code Online (Sandbox Code Playgroud)

替代方案:

SELECT *
FROM articles_categories c
WHERE EXISTS (SELECT 1 
                FROM articles a
               WHERE a.active = TRUE 
                 AND a.category_id = c.id)
Run Code Online (Sandbox Code Playgroud)