首页 > 解决方案 > 使用 sql_mode=only_full_group_by 在 MySQL 中按错误分组

问题描述

尝试以下查询,但我得到了;错误代码:1055。SELECT 列表的表达式 #3 不在 GROUP BY 子句中,并且包含在功能上不依赖于 GROUP BY 子句中的列的非聚合列“PDC.PLG.LogDateTime”;这与 sql_mode=only_full_group_by 不兼容

我知道这是因为只有完整的分组模式;我怎样才能重构这种查询?

SELECT     
SUM(PLG.Qty) AS TotQty,
SUM(PLG.ScrapQty) AS ScrpQty,   
(
SELECT SUM(PLL.Qty) 
FROM ProductionLog AS PLL
INNER JOIN ProductionPlan PPP ON PPP.PlanId = PLL.PlanId
WHERE 
DATE(LogDateTime) = DATE(PLG.LogDateTime) AND 
LogType = 8 AND 
PPP.StationId = PP.StationId

) AS RwrkQty,

DATE(PLG.LogDateTime) AS LogDate,
S.StationName
FROM ProductionLog AS PLG
INNER JOIN ProductionPlan  AS PP ON PLG.PlanId = PP.PlanId
INNER JOIN Station AS S ON S.StationId = PP.StationId
WHERE PLG.Logtype IN (4)

GROUP BY S.StationId,DATE(PLG.LogDateTime)

标签: mysqlsql

解决方案


首先,使用 GROUP 进行正确查询意味着无论您尝试返回的结果字段是什么,您的 GROUP by 都应该包括所有未应用任何聚合的字段(最小值、最大值、总和、平均值等)所以缺少什么是一个额外的列在未聚合的列表中,但也不属于分组依据。因此,要么将此非聚合字段添加到 group by(即使 group by 中的最后一个字段),要么对其应用一些聚合。

现在,清理原始查询的可读性,以了解下一个查询在哪里和/或子查询的可读性。

SELECT     
      SUM(PLG.Qty) AS TotQty,
      SUM(PLG.ScrapQty) AS ScrpQty,   
      ( SELECT SUM(PLL.Qty)
           FROM ProductionLog AS PLL
              INNER JOIN ProductionPlan PPP 
                 ON PPP.PlanId = PLL.PlanId
           WHERE 
                  DATE(LogDateTime) = DATE(PLG.LogDateTime) 
              AND LogType = 8 
              AND PPP.StationId = PP.StationId ) AS RwrkQty,
      DATE(PLG.LogDateTime) AS LogDate,
      S.StationName
   FROM 
      ProductionLog AS PLG
         INNER JOIN ProductionPlan  AS PP 
            ON PLG.PlanId = PP.PlanId
         INNER JOIN Station AS S 
            ON S.StationId = PP.StationId
   WHERE 
      PLG.Logtype IN (4)
   GROUP BY 
      S.StationId,
      DATE(PLG.LogDateTime)

在您的场景中,基于查询的第三列已经在其中聚合,但是对于 OUTER 查询,它没有聚合。为了简化这一点,只需将 IT 包装在 MIN() 中,例如

      MIN( ( SELECT SUM(PLL.Qty)
           FROM ProductionLog AS PLL
              INNER JOIN ProductionPlan PPP 
                 ON PPP.PlanId = PLL.PlanId
           WHERE 
                  DATE(LogDateTime) = DATE(PLG.LogDateTime) 
              AND LogType = 8 
              AND PPP.StationId = PP.StationId ) ) AS RwrkQty,

由于内部查询只返回 1 行,因此总和 1 行将返回相同的值。


推荐阅读