【问题标题】:Mysql MAX 和 GROUP BY
【发布时间】:2022-01-04 01:36:15
【问题描述】:

我想知道为什么这个查询没有给我(我)预期的结果。 我有一张这样的桌子,有很多行。每个城市都有一个独特的地名。每个城市都可以有不同语言的版本。

alternatenameId | geonameid | isoLanguage | alternateName | isPreferredName
1554355            5128581        en          Big Apple
1614284            5128581        en        New York City   
9138713            5128581        en          New York            1

这是查询(我以一个城市为例,但我会扩展到更多城市):

SELECT geonameid, 
       alternateName, 
       MAX(isPreferredName) 
FROM alternatename_new 
WHERE geonameid=5128581 
AND isoLanguage = 'en' 
GROUP BY geonameid

这是查询结果

 geonameid | alternateName | isPreferredName
  5128581     Big Apple            1

但我希望有这个

 geonameid | alternateName | isPreferredName
  5128581      New York            1

我做错了什么?

【问题讨论】:

  • 不完整的 GROUP BY 将在 alternateName 中产生不确定的值,或者如果启用了 ONLY_FULL_GROUP_BY 则会出现错误。
  • MAX() 放在列名周围只会确定输出中该列的值。它不会神奇地为输出中的其他列选择相应的行。你希望SELECT id, Col1, MIN(Col2), MAX(Col2) FROM fubar GROUP BY id 做什么?您需要的是选择您感兴趣的行的东西;通常是WHERE 子句,有时使用连接、子查询等。
  • 对于每个geonameid,是否只有一行isPreferredValue1
  • @MatBailie:是的
  • @luca 然后将isPreferredName = 1 添加到WHERE 子句中,而不是希望使用GROUP BYMAX() 有一些神奇的副作用。

标签: mysql greatest-n-per-group


【解决方案1】:

如果您要执行以下查询,您希望在结果中看到哪个alternateName

SELECT geonameid, alternateName, 
  MAX(isPreferredName),
  MIN(isPreferredName) 
FROM alternatename_new 
WHERE geonameid=5128581 and isoLanguage = 'en' 
GROUP BY geonameid

应该是“大苹果”还是“纽约”?即在具有最大值或最小值的行中找到的alternateName?

如果组中的多行都与isPreferredName 值相关,但每行有不同的alternateName 值怎么办?应该退回哪一个?

如果您使用的另一个聚合函数没有给出出现在任何行上的值怎么办?例如。 COUNT() 还是 AVG()?

答案是 SQL 聚合函数会产生结果,但查询中的其他列与聚合函数的结果无关。

在 MySQL 中,另一列 alternateName 基本上是任意的。它的值来自组中的某一行,而不是找到最大值的行。

实际上,相对于它读取行的索引顺序,MySQL 碰巧从组中的第一 行返回值。但这不是标准的,也不能保证。这只是 MySQL 代码编写方式的巧合。

例如,在 SQLite 中,值来自组中的最后行。

在其他品牌的 SQL 数据库中,以及在 SQL 标准中,这种模棱两可的查询是不合法的。 MySQL 允许它,除非您设置更严格的 SQL 模式。最近的 MySQL 版本默认开启了严格的 SQL 模式,这是一件好事。

您还应该阅读我对以下内容的回答:

【讨论】:

    【解决方案2】:

    似乎 isPreferredName 可能是一个布尔值,1 代表真,0 代表假。如果是这样,只需将 isPreferredName = 1 添加到 WHERE 子句:

    SELECT
      geonameid,
      alternateName,
      isPreferredName
    FROM
      alternatename_new
    WHERE
      isoLanguage = 'en' AND isPreferredName = 1
    

    【讨论】:

    • 我不能使用 isPreferredName = 1 因为当我将查询扩展到所有城市时,并非所有城市都填充了 isPreferredName
    • 在这种情况下,我认为您所要做的就是将_alternateName_添加到您的GROUP BY子句中。
    【解决方案3】:

    您的查询未正确使用分组依据
    在最新版本的mysql(> 5.6)中产生错误(默认情况下)在其他版本的for only_group_by_mode seto上产生不可预测的结果 从你的预期结果中你应该使用

                select  a.geonameid, b.alternateName, a.max_id
        from (
            SELECT geonameid,  MAX(isPreferredName) max_id
            FROM alternatename_new 
            WHERE geonameid=5128581 and isoLanguage = 'en' 
            GROUP BY geonameid 
        ) a 
        inner join alternatename_new b on a.geonameid = b.geonameid and a.max_id = b.isPreferredName
    

    【讨论】:

    • 这个查询给了我一个语法错误。也许对于 2 FROM?
    • 没有在 MAX(isPreferredName) AX 之前缺少 coma
    • @Luca 答案已更新.. 子查询中的列之间缺少逗号..
    猜你喜欢
    • 1970-01-01
    • 2018-06-29
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    • 2010-11-20
    相关资源
    最近更新 更多