如何在不更改 my.ini 文件的情况下使我的查询符合 mysql 5.7

How do I make my query mysql 5.7 compliant without changing my.ini file

我刚刚升级到 mysql 5.7.14,它导致我的一个查询出现问题,我得到了错误。

#1055 - Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'salesinvoice.InvoiceDate' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

现在的解决方案显然是编辑 my.ini 文件并添加这一行

sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

现在这有效了,现在我的查询运行正常,但我宁愿让我的查询符合 mysql 5.7 而不是必须向我的 ini 文件添加行,这可能会或可能不会在我们的服务器上工作.我无法访问服务器上的 ini 文件,但我的本地服务器中有 运行 wampserver 3.06.

这是我的查询

SELECT DATE_FORMAT(`InvoiceDate`,'%Y-%m') as InvoiceDate,
       ROUND((SUM(`Unit_Cost`*`Quantity`)*`ExchangeRate`)+`VATValue`,2) as amount 
FROM `salesinvoice`
LEFT JOIN `salesinvoice_products`
  on `salesinvoice`.`SalesInvoice_id`=`salesinvoice_products`.`SalesInvoice_id`
WHERE `InvoiceDate` < Now()
  and `InvoiceDate` > DATE_ADD(Now(), INTERVAL- 6 MONTH) 
GROUP BY Month(`InvoiceDate`)

如何将查询更改为 mysql 5.7 兼容,错误消息的真正含义是什么?

您的 ActInvoiceDate 不明确..

您不能在 where 中使用别名,您应该更改别名的名称 (你应该在 group by 中使用相同的列)

你的查询之前工作正常,因为以前的版本不检查 select 中是否有列在 group by 子句中不对应..和 for 此列在需要时使用第一个值

因此您的 ExchangeRate、VATValue 列不在分组依据中,为此您可以使用(假的)聚合函数(在本例中我使用 min),因为这些列可能具有常量值

SELECT 
      DATE_FORMAT(`InvoiceDate`,'%Y-%m') as ActInvoiceDate
      ,ROUND((SUM(`Unit_Cost`*`Quantity`)*min(`ExchangeRate`)+min(`VATValue`),2) as amount 
      FROM `salesinvoice`
LEFT JOIN `salesinvoice_products` on `salesinvoice`.`SalesInvoice_id`=`salesinvoice_products`.`SalesInvoice_id`
WHERE `InvoiceDate` < Now() and `InvoiceDate` > DATE_ADD(Now(), INTERVAL- 6 MONTH) 
GROUP BY DATE_FORMAT(`InvoiceDate`,'%Y-%m')

  SELECT 
        DATE_FORMAT(`InvoiceDate`,'%Y-%m') as ActInvoiceDate
        ,ROUND((SUM(`Unit_Cost`*`Quantity`)*min(`ExchangeRate`))+min(`VATValue`),2) as amount 
        FROM `salesinvoice`
  LEFT JOIN `salesinvoice_products` on `salesinvoice`.`SalesInvoice_id`=`salesinvoice_products`.`SalesInvoice_id`
  WHERE `InvoiceDate` < Now() and `InvoiceDate` > DATE_ADD(Now(), INTERVAL- 6 MONTH) 
  GROUP BY ActInvoiceDate

来自FAQ: Server SQL Mode

  • Is the mode dependent on the database or connection?

  • A mode is not linked to a particular database. Modes can be set locally to the session (connection), or globally for the server. you can change these settings using SET [GLOBAL|SESSION] sql_mode='modes'.

在许多平台中,可以运行默认连接查询。

据说,默认模式变得更加严格,不再允许不完整的 GROUP BY 子句,因为它通常是查询错误和结果不正确的标志。

你可以使用这条语句来设置sql_mode

SET GLOBAL sql_mode="STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION";

来自 MySQL 文档

MySQL 5.7.5 and up implements detection of functional dependence. If the ONLY_FULL_GROUP_BY SQL mode is enabled (which it is by default), MySQL rejects queries for which the select list, HAVING condition, or ORDER BY list refer to nonaggregated columns that are neither named in the GROUP BY clause nor are functionally dependent on them. (Before 5.7.5, MySQL does not detect functional dependency and ONLY_FULL_GROUP_BY is not enabled by default.

要告诉 MySQL 接受查询,您可以在产生错误的字段上使用 ANY_VALUE() 函数。

SELECT ANY_VALUE(DATE_FORMAT(`InvoiceDate`,'%Y-%m')) as `formatedInvoiceDate`,
       ROUND((SUM(`Unit_Cost`*`Quantity`)*`ExchangeRate`)+`VATValue`,2) as `amount` 
FROM `salesinvoice`
LEFT JOIN `salesinvoice_products`
  on `salesinvoice`.`SalesInvoice_id`=`salesinvoice_products`.`SalesInvoice_id`
WHERE `InvoiceDate` < Now()
  and `InvoiceDate` > DATE_ADD(Now(), INTERVAL- 6 MONTH) 
GROUP BY Month(`InvoiceDate`).

或者,禁用 ONLY_FULL_GROUP_BY

关于 ANY_VALUE() 函数的更多信息可以在 MySQL 关于 Miscellaneous Functions 的文档中找到(请务必阅读示例)。

Synoptically, ANY_VALUE() function is useful for GROUP BY queries when the ONLY_FULL_GROUP_BY SQL mode is enabled, for cases when MySQL rejects a query that you know is valid for reasons that MySQL cannot determine. The function return value and type are the same as the return value and type of its argument, but the function result is not checked for the ONLY_FULL_GROUP_BY SQL mode.