GROUP BY字段的顺序会影响MySQL查询结果
我正在学习MySQL,并在一个有实践问题的网站上进行练习(未命名,但它是问题81)。问题在于分组后字段的顺序。我确信GROUP BY后面的字段序列会影响基于所报告的隐藏表中预期行数和实际行数之间的比较的查询结果。从本网站和其他网站的大量阅读中,我的理解是,这并不重要 任务是:GROUP BY字段的顺序会影响MySQL查询结果,mysql,group-by,Mysql,Group By,我正在学习MySQL,并在一个有实践问题的网站上进行练习(未命名,但它是问题81)。问题在于分组后字段的顺序。我确信GROUP BY后面的字段序列会影响基于所报告的隐藏表中预期行数和实际行数之间的比较的查询结果。从本网站和其他网站的大量阅读中,我的理解是,这并不重要 任务是: From Outcome table, retrieve all rows for that month (months) in view of a year, in which total value of exp
From Outcome table, retrieve all rows for that month (months)
in view of a year, in which total value of expenses (out) is maximal.
表格说明如下:
Outcome(code, point, date, out) where code is the primary key,
point is a simple integer, date is in the format datetime, and out is a currency value.
我的问题是:
SELECT code,point,date,`out` outc FROM outcome
WHERE EXTRACT(MONTH FROM date) =
(SELECT mon bestmonth FROM
(SELECT MAX(sout), mon,yr FROM
(SELECT SUM(outc) sout,mon,yr FROM
(SELECT EXTRACT(MONTH FROM date) mon, `out` outc,
date,EXTRACT(YEAR FROM date) yr FROM outcome
) maxmonth GROUP BY mon,yr
) peak
) tmonth
)
AND EXTRACT(YEAR FROM date) =
(SELECT yr bestyear FROM
(SELECT MAX(yout), mon,yr FROM
(SELECT SUM(outy) yout,mon,yr FROM
(SELECT EXTRACT(MONTH FROM date) mon, `out` outy,
date,EXTRACT(YEAR FROM date) yr FROM outcome
) maxyear GROUP BY yr,mon
) peakb
) tyear
)
虽然不是一个优雅的查询,但我想理解为什么在maxmonth和maxyear子查询中将顺序从“groupbymon,yr”更改为“groupbyyr,mon”会产生任何效果
在maxmonth子查询中,“按mon、yr分组”结果为:
Wrong Your query produced correct result set on main database,
but it failed test on second, checking database
* Wrong number of records (less by 6)
Wrong Your query produced correct result set on main database,
but it failed test on second, checking database
* Wrong number of records (less by 11)
对于同一maxmonth子查询,“按年份分组,按月份分组”的结果为:
Wrong Your query produced correct result set on main database,
but it failed test on second, checking database
* Wrong number of records (less by 6)
Wrong Your query produced correct result set on main database,
but it failed test on second, checking database
* Wrong number of records (less by 11)
您需要了解,group by 1列并不意味着所有其他列都将具有分组列的值 例如,给定表格:
customer | value | date
1 | 2 | 2015-01-03
1 | 3 | 2015-01-05
2 | 3 | 2015-01-02
2 | 4 | 2015-01-03
2 | 5 | 2015-01-04
如果你使用
select customer, max(value), date from table group by customer
你的结果可能是
customer | max(value) | date
1 | 3 | 2015-01-03
2 | 5 | 2015-01-02
这不是你想要的。。。因为agregation函数仅适用于该列
它可以帮助:
select year(date) yr, month(date) mon, sum(outc) totalOfMonth from outcome group by yr, mon order by totalOfMonth
groupby
当前会影响返回结果的顺序(尽管MySQL警告这种行为将来可能会改变,所以不要依赖它)。由于包含这些GROUP BY查询的查询隐含了不包括非聚合字段的GROUP BY
子句,因此为这些字段选择返回的值在官方上是不确定的
(它通常是遇到的第一个或最后一个值,我避免这样的查询,因为它们是不可预测的)
编辑/供参考:大多数其他RDBMS甚至不允许使用GROUP BY子句进行查询,这些子句不包括所有非聚合字段。MySQL甚至允许它被批评;虽然这是我的假设,但最初的意图(以及最近版本的服务器设置似乎证实了这一点)是允许进行更简洁的查询,其中查询作者知道每个分组值集只有一组非聚合字段的值;例如,当在一个表上按主键分组时,不包括来自可能变化的联接表的字段(例如:只有非聚合、非分组字段来自PK为分组标准一部分的表)。基本上,我对答案的解释是,在使用GROUP by时,始终使用所有相关的非聚合字段。如果表中涉及其他字段,则可能存在问题,在这种情况下,最大值可能不是真正的最大值,并且可能是任意的。原始查询在结果表(maxmonth派生表)上包含GROUP BY,该表不包含所有非聚合字段,GROUP BY的结果可疑 据我所知,答案的要点是: 1) 具有聚合值(如表的MAX)的查询应报告与GROUP BY子句(customer)中包含的字段值相对应的实际MAX值,但GROUP BY中未包含的字段(如date)不一定与正确的MAX值相对应。从上面的第一个答案中可以明显看出,客户和最大值是正确的,但日期(不包括在GROUP BY中)可能实际上与客户/最大值行不对应。使用仅包含相关非聚合值(月和年)的派生表(formattedOutMonthYear_sq表)并创建新的派生表(groupedOutMonthYear_sq表)若要执行合计和,应为月份和年份生成正确的值,但如果使用的是结果表而不是formattedOutMonthYear表,则代码和点字段可能不正确 2) 使用诸如MAX(峰值表)之类的聚合而不显式地将任何GROUP BY包含在非聚合字段中,可能会导致意外结果。在原始代码中,由于隐式分组,GROUPBY子句中包含非聚合的派生表上的聚合最大值可能仍然是集群的 GROUP BY仍然包含多个列,但我从上面的答案中得出的解释是,如果包含所有非聚合列(Uueerdo),并且不从查询中推断其他字段(Renan),则可以接受多个列 不幸的是,运行查询会导致运行时错误,这是不幸的。感谢您解释我观察到的结果,我将把这个逻辑结合到查询编写中
SELECT o.code cd,o.point pnt ,o.date dt,`out` expense,mdt FROM outcome o
JOIN
(SELECT EXTRACT(MONTH FROM date) mdt, EXTRACT(YEAR FROM date) ydt, code FROM outcome
) mnth
ON mnth.code = o.code
WHERE mdt =
(
SELECT distinct mon topMonth from
(SELECT SUM(outm) allOutMonth, mon, yr FROM
(SELECT EXTRACT(MONTH FROM date) mon, `out` outm, EXTRACT(YEAR FROM date) yr
FROM outcome
) formattedOutMonthYear_sq GROUP BY yr, mon
) topMonth_sq
WHERE topMonth_sq.allOutMonth >= all
(SELECT allOutMonth from
(SELECT SUM(outm) allOutMonth, mon, yr FROM
(SELECT EXTRACT(MONTH FROM date) mon, `out` outm,
EXTRACT(YEAR FROM date) yr
FROM outcome
) formattedOutMonthYear_sq GROUP BY yr, mon
) groupedOutMonthYear_sq
)
)
AND ydt =
(
SELECT yr topTopYear from
(SELECT SUM(outm) allOutYear, mon, yr FROM
(SELECT EXTRACT(MONTH FROM date) mon, `out` outm,
EXTRACT(YEAR FROM date) yr
FROM outcome
) formattedOutYearMonth_sq GROUP BY yr, mon
) topYear_sq
WHERE topYear_sq.allOutYear >= all
(SELECT allOutYear from
(SELECT SUM(outm) allOutYear, mon, yr FROM
(SELECT EXTRACT(MONTH FROM date) mon,
`out` outm, EXTRACT(YEAR FROM date) yr
FROM outcome
) formattedOutMonthYear_sq GROUP BY yr, mon
) groupedOutYearMonth_sq
)
)
我想我明白你的意思。为了解决这个问题,我删除了MAX并使用了一个新的子查询。不幸的是,在网站上测试的查询导致运行时错误。这(由于评论限制发布在下面)是一个好的解决方法吗?谢谢你的回复。这是一个疯狂的问题。这是原问题81的译文吗?