PostgreSQL - GROUP BY子句

时间:2013-09-24 20:41:52

标签: sql postgresql group-by aggregate-functions

我想按标签搜索,然后列出所有带有该标签的文章,以及它们匹配的给定标签的数量。例如,我可能有:

 Page1 - 2 (has css and php tag)
 Page2 - 1 (has only css tag)

查询:

SELECT COUNT(t.tag)
FROM a_tags t
JOIN w_articles2tag a2t ON a2t.tag = t.id 
JOIN w_article a ON a.id = a2t.article 
WHERE t.tag = 'css' OR t.tag = 'php'
GROUP BY t.tag
LIMIT 9

当我只提出COUNT(t.tag)查询时,我得到的结果还不错。但如果我追加,例如我的文章ID出现以下错误:

  

错误:列“a.title”必须出现在GROUP BY子句中或用于聚合函数      第1行:SELECT COUNT(t.tag),a.title FROM a_tags t

如何将所述列添加到此查询中?

2 个答案:

答案 0 :(得分:8)

使用“GROUP BY”子句时,需要包含未在聚合函数中分组的所有列。尝试将标题添加到GROUP BY列表,或选择“min(a.title)”。

SELECT COUNT(t.tag), a.title FROM a_tags t
JOIN w_articles2tag a2t ON a2t.tag = t.id 
JOIN w_article a ON a.id = a2t.article 
WHERE t.tag = 'css' OR t.tag = 'php' GROUP BY t.tag, a.title LIMIT 9

答案 1 :(得分:6)

首先,澄清Postgres 9.1或更高版本(quoting release notes of 9.1)......

  

在主要时,允许查询目标列表中的非GROUP BY列   key在GROUP BY子句中指定(Peter Eisentraut)

更多相关答案:
Return a grouped list with occurrences using Rails and PostgreSQL

接下来,问题和@Michael's answer中的查询已经倒退了逻辑。我们想要计算每篇文章与匹配的标签数量,而不是有多少文章有特定标签。因此,我们需要GROUP BY w_article.id,而不是a_tags.id

  

列出所有带有该标签的文章,以及它们匹配的给定标签的数量

修复

SELECT COUNT(t.tag) AS ct, a.* -- any column from a allowed ...
FROM   a_tags         t
JOIN   w_articles2tag a2t ON a2t.tag = t.id 
JOIN   w_article      a   ON a.id = a2t.article 
WHERE  t.tag IN ('css', 'php')
GROUP  BY a.id           -- ... since grouped by pk column of a
LIMIT  9

假设idw_article的主键 但是,这样做的形式更快同时:

SELECT a.*, ct
FROM  (
   SELECT a2t.article AS id, COUNT(*) AS ct
   FROM   a_tags         t
   JOIN   w_articles2tag a2t ON a2t.tag = t.id 
   GROUP  BY a.article 
   LIMIT  9      -- LIMIT early - cheaper
   ) sub
JOIN   w_article a USING (id);  -- attached alias to article in the sub

更多来自昨天这个密切相关的答案:
Why does the following join increase the query time significantly?

顺便说一句:使用通用的非描述性id作为列名是一种反模式。在两个表中调用它article_id等。更容易加入,您不必一直在查询中使用别名。