为啥没有聚合函数的选择列需要成为 MySQL 中 Group by 子句的一部分?

Posted

技术标签:

【中文标题】为啥没有聚合函数的选择列需要成为 MySQL 中 Group by 子句的一部分?【英文标题】:Why columns in selection without aggregate function needs to be part of Group by clause in MySQL?为什么没有聚合函数的选择列需要成为 MySQL 中 Group by 子句的一部分? 【发布时间】:2021-01-16 17:13:08 【问题描述】:

这里是SQLZOO Join https://sqlzoo.net/wiki/The_JOIN_operation上第11题的表格链接和详细说明。

问题是询问'对于每场涉及'POL'的比赛,显示比赛ID、日期和进球数。'

下面是我的 SQL 代码

SELECT matchid, mdate, COUNT(player)
FROM game JOIN goal ON id = matchid
WHERE (team1 = 'POL' OR team2 = 'POL')
GROUP BY matchid

错误消息是'gisq.game.mdate' isn't in GROUP BY。结果在我的代码的最后一行我必须做GROUP BY matchid, mdate

我现在正在学习 SQL,谁能帮我理解为什么我必须同时按 matchidmdate 而不是其中一个分组?

提前感谢您的热心帮助。

【问题讨论】:

请注意,手册对此进行了深入介绍。 这是一个常见问题解答。请在考虑发布之前阅读您的教科书和/或手册和谷歌任何错误消息或您的问题/问题/目标的许多清晰、简洁和精确的措辞,有和没有您的特定字符串/名称和站点:***.com 和标签;阅读许多答案。如果您发布问题,请使用一个短语作为标题。反映你的研究。请参阅How to Ask 和投票箭头鼠标悬停文本。 【参考方案1】:

当存在 GROUP BY 或存在任何聚合函数时,SELECT 列表表达式引用未分组的列是无效的,除非在聚合函数中(如 sum、max、min 等,它们将为每个组返回单个值),因为否则会为未分组的列返回多个可能的值,并且 select 不会只返回一个任意值。

但是,有多种解决方法。

选项 1. 你自己做的,将另一列添加到 group by as -

    SELECT 
          matchid
        , mdate
        , COUNT(player)
    FROM game 
      JOIN goal 
         ON id = matchid
   WHERE (team1= 'POL' OR team2= 'POL')
   GROUP BY matchid, mdate;

选项 2。此外,在这种情况下,您可以在另一列上添加聚合函数,如下所示(因为字段 mdate 在功能上取决于匹配 id,因此您可以这样做。您可以使用任何聚合函数会选择一个值)

    SELECT
          matchid
        , max(mdate) as mdate
        , COUNT(player)
    FROM game 
      JOIN goal 
         ON id = matchid
   WHERE (team1= 'POL' OR team2= 'POL')
   GROUP BY matchid;

选项 3。您可以在子查询中计算聚合,然后将其与自身连接以获得您需要显示的其他列,如下所示

    select 
          t1.matchid
        , t2.mdate
        , t1.count_player
    from
    (SELECT 
          matchid
        , COUNT(player) as count_player
    FROM game 
      JOIN goal 
         ON id = matchid
   WHERE (team1= 'POL' OR team2= 'POL')
   GROUP BY matchid) t1 
   join game t2 on t1.matchid = t2.id;

选项4.你也可以使用窗口函数并获取不同的元组值

    SELECT distinct 
                     matchid
                   , mdate
                   , COUNT(player) over(partition by matchid) as 
    count_player
    FROM game 
      JOIN goal 
         ON id = matchid
   WHERE (team1= 'POL' OR team2= 'POL');

【讨论】:

以上是关于为啥没有聚合函数的选择列需要成为 MySQL 中 Group by 子句的一部分?的主要内容,如果未能解决你的问题,请参考以下文章

为啥不能再where语句中直接使用聚合函数

选择列表中的列无效,因为该列没有包含在聚合函数或 GROUP BY 子句中

为啥聚合函数不能放在where后面?

选择列表中的列无效,因为该列没有包含在聚合函数或 GROUP BY 子句中

为啥 CROSS APPLY 与列和聚合函数需要 Group by

postgreSQL 选择聚合函数中未使用的附加列