【问题标题】:PostgreSQL - GROUP BY clausePostgreSQL - GROUP BY 子句
【发布时间】:2013-09-24 20:41:51
【问题描述】:

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

 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

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

【问题讨论】:

    标签: sql postgresql group-by aggregate-functions


    【解决方案1】:

    当您使用“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
    

    【讨论】:

    • 是的,我尝试添加 MAX(a.title),然后按 tags_count DESC 的最后顺序添加 .. 解决了它,但我不确定你为什么需要添加例如。在你的情况下 MIN(a.title) .. 当我从 MySQL 转移时,我认为情况并非如此,所以这就是为什么它有点奇怪:O
    • MySQL 的group by 是非标准且模棱两可的stackoverflow.com/a/1777448/375874
    • 明确地说,mysql 不需要在选择列表中未出现在 group by 中的列上使用聚合函数(如 MIN 或 MAX)。这种行为在某些情况下会导致意想不到的结果,所以postgres确实有这个要求,你已经注意到它与mysql不同。
    • @Adrian:您可能想阅读此:rpbouman.blogspot.de/2007/05/debunking-group-by-myths.html 和此:mysqlperformanceblog.com/2006/09/06/…,以了解 MySQL 的“松散”(不是说:不正确)group by 处理可能存在的缺陷。跨度>
    【解决方案2】:

    Postgres 9.1 或更高版本,quoting the release notes of 9.1 ...

    当primary时允许查询目标列表中的非GROUP BY列 密钥在 GROUP BY 子句中指定 (Peter Eisentraut)

    SQL 标准允许这种行为,并且由于主键, 结果是明确的。

    相关:

    问题和@Michael's answer 中的查询具有向后的逻辑。我们想计算有多少标签匹配每篇文章,而不是有多少文章有某个标签。所以我们需要GROUP BY w_article.id,而不是a_tags.id

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

    修复这个:

    SELECT count(t.tag) AS ct, a.*  -- any column from table 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 PK is in GROUP BY
    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 1
       LIMIT  9      -- LIMIT early - cheaper
       ) sub
    JOIN   w_article a USING (id);  -- attached alias to article in the sub
    

    昨天的密切相关的答案:

    【讨论】:

    • Erwin,我邀请您在提及其他贡献者时更加鼓舞人心。问题和答案在原则上并不是不正确的,它们只是基于不同的原则是正确的。提出的问题是语法问题,而不是语义问题。 Adrian 提供了代码来支持语法问题。答案提供了与问题相同的详细程度,并且仅限于所提出的问题。作为回应,阿德里安评论说,“这解决了它。”您选择回答有关 GROUP BY 的更多详细信息,并且还改进了语义。我完全赞成。另一个主体也很有用。
    • @MichaelKrebs:甚至没有任何远程冒犯或人身攻击。也不是故意的。对不起,如果我踩到了你的脚趾。删除了粗体和一些噪音。只是指出出了什么问题,这就是我们在 SO 上所做的事情。你有两个赞成半正确的答案。没那么糟。欢迎来到 Stackoverflow。
    猜你喜欢
    • 2021-11-13
    • 1970-01-01
    • 2016-04-03
    • 2012-04-27
    • 2012-04-20
    • 2016-05-09
    • 2018-03-23
    • 1970-01-01
    • 2011-12-17
    相关资源
    最近更新 更多