SQL 分组的结果与预期不符

Posted

技术标签:

【中文标题】SQL 分组的结果与预期不符【英文标题】:Results of SQL grouping not as intended 【发布时间】:2015-05-27 13:04:12 【问题描述】:

介绍详情:

我在使用客户端 12c 查询 Oracle SQL Developer 时遇到问题。我研究了关于 SO 的其他几个问题,并在 Google 上搜索了这个问题的答案,但最终所有的答案都是在 GROUP BY 子句中包含所有没有聚合函数的列。

我想要的是每年、每周和每天(分别为FD.YEARFD.WEEKFD.DT)为每个类别 (PG.CAT) 获得一个结果。我想总结单位、小时数、错误 (GE.QTY) 和总小时数。我还对两列执行乘法和除法,并连接最多四个其他表。

查询:

`SELECT 
  FD.YEAR, 
  FD.WEEK, 
  PG.DT, 
  PG.CAT, 
  SUM(PG.UNITS) AS UNITS, 
  SUM(PG.HOURS) AS HOURS, 
  PM.MTM,
  PM.MTM * PG.HOURS AS ADJ_MTM,
  (PG.UNITS / (PM.MTM * PG.HOURS)) AS PERC_STANDARD,
  SUM(CASE WHEN GE.QTY IS NULL THEN 0 ELSE GE.QTY END) AS QTY,
  SUM(WH.TOTALHOURS) AS TOTALHOURS 
FROM 
  PROD_GUNS PG 
INNER JOIN PROD_MTM PM 
  ON PG.CAT = PM.CATEGORY 
  AND PM.DEPTNO = '018' 
  AND PG.DT BETWEEN PM.START_DT AND PM.END_DT 
INNER JOIN FISCAL_DATES_DAYS FD 
  ON PG.DT = FD.DT 
LEFT OUTER JOIN PROD_GUNS_ERRORS GE 
  ON PG.EID = GE.EID 
  AND PG.DT = GE.DT 
INNER JOIN WEEKLY_HOURS WH
  ON FD.WEEK = WH.DT_WEEK
  AND FD.YEAR = WH.DT_YEAR
  AND PG.EID = WH.EEXX31
GROUP BY 
  FD.YEAR, 
  FD.WEEK, 
  PG.DT, 
  PG.CAT, 
  PM.MTM,
  PM.MTM * PG.HOURS,
  (PG.UNITS / ( PM.MTM * PG.HOURS)) 
HAVING 
  FD.YEAR = '2015' 
  AND FD.WEEK = '1' 
  AND PG.DT = '29-DEC-14' 
  AND PG.CAT = 'Picking'
ORDER BY 
  PG.DT;`

实际结果:

2015    1   29-DEC-14   Picking 46  0.5  68 34      1.35294117647058823529411764705882352941    0   32.21
2015    1   29-DEC-14   Picking 831 7.72 68 524.96  1.58297775068576653459311185614142029869    0   29.35

预期结果:

2015    1   20-Dec-14   Picking 877 8.22 68 558.96   1.21654501216545     0     61.59

问题:

使用我上面的聚合和分组,为什么这不能给我预期的结果?提前感谢大家提供的任何指导。

【问题讨论】:

如果您只是按列分组,而不是表达式(计算)? 这样做会导致以下错误ORA-00979: not a GROUP BY expression 00979. 00000 - "not a GROUP BY expression" 这就是它如此令人沮丧的原因。所有其他问题/答案状态为在 GROUP BY 中包含没有聚合的所有列。好吧,这样做仍然会返回一个抱怨 GROUP BY 子句的错误。 group by 子句的全部意义在于它告诉查询为 grouped by 字段中的每个唯一值组合返回一个单独的行。如果(对于给定的年、周、日和类别)您有 10 个单独的行,您希望显示哪个 MTM 值? 【参考方案1】:

尝试 SUM/AVG(取决于您的需要)PM.MTM * PG.HOURS AS ADJ_MTM 和 (PG.UNITS / (PM.MTM * PG.HOURS)) AS PERC_STANDARD,而不是按它们分组:

SELECT 
  FD.YEAR, 
  FD.WEEK, 
  PG.DT, 
  PG.CAT, 
  SUM(PG.UNITS) AS UNITS, 
  SUM(PG.HOURS) AS HOURS, 
  PM.MTM,
  SUM(PM.MTM * PG.HOURS )AS ADJ_MTM,
  SUM((PG.UNITS / (PM.MTM * PG.HOURS))) AS PERC_STANDARD,
  SUM(CASE WHEN GE.QTY IS NULL THEN 0 ELSE GE.QTY END) AS QTY,
  SUM(WH.TOTALHOURS) AS TOTALHOURS 
FROM 
  PROD_GUNS PG 
INNER JOIN PROD_MTM PM 
  ON PG.CAT = PM.CATEGORY 
  AND PM.DEPTNO = '018' 
  AND PG.DT BETWEEN PM.START_DT AND PM.END_DT 
INNER JOIN FISCAL_DATES_DAYS FD 
  ON PG.DT = FD.DT 
LEFT OUTER JOIN PROD_GUNS_ERRORS GE 
  ON PG.EID = GE.EID 
  AND PG.DT = GE.DT 
INNER JOIN WEEKLY_HOURS WH
  ON FD.WEEK = WH.DT_WEEK
  AND FD.YEAR = WH.DT_YEAR
  AND PG.EID = WH.EEXX31
GROUP BY 
  FD.YEAR, 
  FD.WEEK, 
  PG.DT, 
  PG.CAT, 
  PM.MTM 
HAVING 
  FD.YEAR = '2015' 
  AND FD.WEEK = '1' 
  AND PG.DT = '29-DEC-14' 
  AND PG.CAT = 'Picking'
ORDER BY 
  PG.DT;

【讨论】:

我也正要指出这一点。您忘记了SUM ADJ_MTM,这会将它们转换为输出中的唯一行,并防止它们汇总为一行。 @StefanYordanov 你是天才!这正是我想要的。我会在几分钟内接受你的回答。说真的,谢谢你的帮助。我花了一天半的时间试图弄清楚这一点!

以上是关于SQL 分组的结果与预期不符的主要内容,如果未能解决你的问题,请参考以下文章

LINQ - 按多个键分组未给出预期结果

php poker 生成的随机结果与预期不符

Java - 比较两个 ZonedDateTime 时的结果与预期不符

Python-在while循环期间将列表附加到列表-结果与预期不符[重复]

SQL之复杂查询与视图

SQL之复杂查询与视图