【问题标题】:How to change Mysql query (GROUP BY) Error with sql_mode=only_full如何更改 Mysql 查询(GROUP BY)错误与 sql_mode=only_full
【发布时间】:2018-01-08 06:47:00
【问题描述】:

我有一个包含这些列的大型 MySql 表:

id  int(10) unsigned Auto Increment  
pr_id   int(10) unsigned     
temp_air    varchar(255) NULL        
created_at  timestamp NULL   
updated_at  timestamp NULL

我想获取 24 小时前数据的行,并从该选择数据中获取每小时的数据。

我试过的查询是:

SELECT *
FROM `statistics`
WHERE DATE(created_at) = CURDATE()- INTERVAL 1 DAY
GROUP BY  
EXTRACT(HOUR FROM created_at)
ORDER BY
EXTRACT(HOUR FROM created_at)

并且出现错误:

查询错误 (1055):SELECT 列表的表达式 #1 不在 GROUP BY 子句中,并且包含非聚合列 'statistic.statistics.id' 它在功能上不依赖于 GROUP BY 子句中的列; 这与 sql_mode=only_full_group_by 不兼容

我必须如何更改我的查询?我的错误在哪里?

【问题讨论】:

  • group by 子句是将数据汇总成组,而不是按小时显示您的数据。后者需要分页,而不是分组。
  • Extract 是一个 oracle 函数而不是 mysql 您要转换为 mysql 吗?
  • @P.Salmon 了解 MySQL 函数 EXTRACT()
  • 请不要标记无关的产品。 Microsoft SQL Server 与 MySQL 无关。

标签: php mysql


【解决方案1】:

SELECT *GROUP BY 不兼容。在 5.7.5 版本之前,MySQL 曾经接受无效的GROUP BY 查询,但它返回了indeterminate values

GROUP BY 查询不会从数据库返回行;它即时生成它返回的记录。从根据GROUP BY 子句生成的每一组行中,它生成一行。 SELECT *GROUP BY 没有意义;如果一组包含多于一行,它应该为id 列返回什么值,f.e.?

如果您不想每小时生成一行,那么 GROUP BY 不是您所需要的。

但是如果你想每小时生成一行,那么查询应该是这样的:

SELECT EXTRACT(HOUR FROM created_at), AVG(temp_air) AS temp_air
FROM `statistics`
WHERE created_at >= DATE_SUB(CURTIME(), INTERVAL 1 DAY)
GROUP BY EXTRACT(HOUR FROM created_at)
ORDER BY EXTRACT(HOUR FROM created_at)

原始WHERE 条件(DATE(created_at) = CURDATE()- INTERVAL 1 DAY)使用的DATE() 函数不允许 MySQL 使用索引来过滤要处理的行,它需要读取整个表数据。它现在可以使用索引(假设create_at 列上有索引)。

【讨论】:

  • 另外我将查询更改为:SET sql_mode = ''; SELECT * FROM statistics WHERE DATE(created_at) = CURDATE()- INTERVAL 1 DAY GROUP BY EXTRACT(HOUR FROM created_at) ORDER BY EXTRACT(HOUR FROM created_at) 它也有效。谢谢 axiac!
  • Mysql 对非法 group by 子句的处理已经并且仍然是可配置的。只是更改了默认设置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-13
  • 2012-06-12
  • 2016-02-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多