PostgreSQL中的HAVING子句

时间:2011-03-31 07:56:00

标签: 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

我不知道原因,但此查询导致错误:

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

2 个答案:

答案 0 :(得分:13)

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

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

它基本上说:

  

HAVING的存在会导致查询   进入分组查询即使有   没有GROUP BY子句。这是一样的   就像查询时会发生什么   包含聚合函数但不包含   GROUP BY子句。所有选定的行   被认为是一个单一的群体,   以及SELECT列表和HAVING子句   只能从中引用表列   在集合函数内。这样的   如果是,查询将发出单行   HAVING条件为真,零行如果   事实并非如此。

The same is also explained in this blog post,其中显示HAVING如果没有GROUP BY隐含地暗示SQL:1999标准“总计”,即GROUP BY ( )子句(不支持的PostgreSQL)

由于您似乎不想要单行HAVING子句可能不是最佳选择。

考虑到您的实际查询和您的要求,只需将整个内容和JOIN articles_categories重写为articles

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

替代:

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

答案 1 :(得分:0)

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

应该没问题......或许更简单;)