我需要从数据集中获取每种行业类型的平均值,最小值和最大值。当我使用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;
答案 0 :(得分:0)
SQL标准要求GROUP BY
子句包含 ALL NOT 使用aggregate function
的列(即min(),max( ),avg()等。)。
然而,MySQL为SQL92及更早版本不允许选择列表的查询, HAVING条件或ORDER BY列表指的是非聚合列 未在GROUP BY子句中命名。 https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html
GROUP BY
实现了非标准的附加功能,而在旧版本的MySQL中,它违反了非标准方法。 (有一个服务器设置,您可以更改为从标准语法转换为非标准语法进行分组。)自MySQL 5.7.5起,默认设置已更改为SQL标准方法。
MySQL 5.7.5及更高版本实现了对功能依赖的检测。如果 启用ONLY_FULL_GROUP_BY SQL模式(默认情况下是这样), MySQL拒绝选择列表,HAVING条件或的查询 ORDER BY列表引用既未命名的非聚合列 GROUP BY子句在功能上也不依赖于它们。
几乎可以肯定,原始查询不起作用的原因是出于上述考虑。许多人会告诉你,使用非标准方法是不好的做法,事实上,如果你进一步研究这个话题,你会发现非标准方法会返回"不确定结果"对于未包含在group by子句中的所有列(除极少数情况外)。你总是更好地使用标准方法。 e.g。
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