【问题标题】:How can I get MIN, MAX, AVG working with an innerjoin?如何使用内部联接获得 MIN、MAX、AVG?
【发布时间】:2018-04-02 17:28:01
【问题描述】:

我需要从数据集中获取每种行业类型的平均值、最小值和最大值。当我使用 MIN、MAX、AVG 函数时,它只返回与 Amount 列相同的值。

我的尝试

SELECT c.Custid, c.Cname, c.City, c.IndustryType, o.OrderNo, o.OrderDate, o.SalesPersonID, o.Amount, 
AVG(o.Amount) AS 'Average Amount',
MIN(o.Amount) AS 'Minimum Amount',
MAX(o.Amount) AS 'Maximum Amount'
FROM customer c
INNER JOIN orders o
ON c.custid = o.custid
GROUP BY c.IndustryType,o.orderdate;

【问题讨论】:

  • 删除第一行除c.IndustryType之外的所有内容。还要从 GROUP BY 子句中删除 o.orderdate
  • 发布您的表定义和一些与您的问题相关的示例数据集
  • @Paul Spiegel,好的,但我不明白为什么它会破坏我的结果,我可以在结果中显示所有字段 id、name、city 等吗?
  • 对不起,我试图解释这一点,但我觉得我会写文档(即使是答案也会很宽泛)。所以请先阅读the official documentation

标签: mysql


【解决方案1】:

SQL 标准要求 GROUP BY 子句包含 ALL 那些 NOT 使用 aggregate function 的列(即 min(),max(),avg( ) 等等)。

SQL92 和更早的版本不允许选择列表的查询, HAVING 条件或 ORDER BY 列表指的是非聚合列 未在 GROUP BY 子句中命名。 https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

然而,MySQL 为 GROUP BY 实现了一个额外的功能,这是非标准的,并且在旧版本的 MySQL 中它默认为非标准方法。 (有一个服务器设置,您可以将其更改为从标准语法转换为非标准语法进行分组。)自 MySQL 5.7.5 起,默认设置更改为 SQL 标准方法。

MySQL 5.7.5 及更高版本实现了功能依赖检测。如果 ONLY_FULL_GROUP_BY SQL 模式已启用(默认情况下), MySQL 拒绝选择列表、HAVING 条件或 ORDER BY 列表指的是未在其中命名的非聚合列 GROUP BY 子句在功能上也不依赖于它们。

见:ONLY_FULL_GROUP_BY

几乎可以肯定,您的原始查询不起作用的原因是出于上述考虑。许多人会告诉您,使用非标准方法是不好的做法,实际上,如果您进一步研究该主题,您将了解到非标准方法会为所有未包含在 group by 子句中的列返回“不确定的结果”(除了在极少数情况下)。你最好一直使用标准方法。例如

SELECT
      c.IndustryType
    , o.OrderDate
    , AVG(o.Amount) AS "Average Amount"
    , MIN(o.Amount) AS "Minimum Amount"
    , MAX(o.Amount) AS "Maximum Amount"
FROM customer c
INNER JOIN orders o ON c.custid = o.custid
GROUP BY
      c.IndustryType
    , o.OrderDate
;

SELECT
      c.Custid
    , c.Cname
    , c.City
    , c.IndustryType
    , o.OrderNo
    , o.OrderDate
    , o.SalesPersonID
    , o.Amount
    , AVG(o.Amount) AS "Average Amount"
    , MIN(o.Amount) AS "Minimum Amount"
    , MAX(o.Amount) AS "Maximum Amount"
FROM customer c
INNER JOIN orders o ON c.custid = o.custid
GROUP BY
      c.Custid
    , c.Cname
    , c.City
    , c.IndustryType
    , o.OrderNo
    , o.OrderDate
    , o.SalesPersonID
    , o.Amount
;

值得一提的是,您的原始查询似乎需要为 (IndustryType & OrderDate) 的每个唯一组合计算聚合,但要在更多详细信息行上重复这些聚合。有一些“窗口函数”允许发生这种情况,这些函数正在开发中并打算与 MySQL 8.x 一起发布,这些函数已经存在于其他数据库中,例如 DB2、Oracle、SQL Server、Postgre、SQL Lite、MariaDB(以及更多)。

窗口聚合的语法如下所示:

SELECT
      c.Custid
    , c.Cname
    , c.City
    , c.IndustryType
    , o.OrderNo
    , o.OrderDate
    , o.SalesPersonID
    , o.Amount
    , AVG(o.Amount) OVER(PARTITION BY c.IndustryType, o.OrderDate)
        AS "Average Amount" 
    , MIN(o.Amount) OVER(PARTITION BY c.IndustryType, o.OrderDate)
        AS "Minimum Amount"
    , MAX(o.Amount) OVER(PARTITION BY c.IndustryType, o.OrderDate)
        AS "Maximum Amount"
FROM customer c
INNER JOIN orders o ON c.custid = o.custid

【讨论】:

    猜你喜欢
    • 2012-11-05
    • 2018-06-06
    • 1970-01-01
    • 2023-04-10
    • 2017-11-01
    • 1970-01-01
    • 2023-03-13
    • 2013-07-18
    • 1970-01-01
    相关资源
    最近更新 更多