mysql - MYSQL Full GROUP BY 的解决方法

标签 mysql sql database query-optimization mysql-5.7

我正在处理一个查询,它需要尽可能通用以便重用。 查询涉及GROUP BY。

但是我不能指定列,因为我需要它是通用的。

查询目的:

  • 使用日期列为每一行分配一个时间键。
  • 然后我使用 GROUP BY 只获取组的几个值。
  • 基本上我想做的是减少给定日期的点数。
  • 因此,如果一天有 4 个点,我会使用 GROUP BY 将一天中的相同点减少到 2 个点,然后选择相同的点到一个新的数据库中。

查询

SELECT * FROM
   (SELECT h.* FROM testdb h
   WHERE h.date <= '2016-01-02 23:30:00'
   GROUP BY FLOOR(UNIX_TIMESTAMP(h.date)/((1440/2)*60))
   UNION
   SELECT c.* FROM testdb c
   WHERE c.date> '2016-01-02 23:30:00') m;

我可以通过禁用 ONLY_FULL_GROUP_BY 模式在 MySQL v5.7 及更高版本中运行上述查询。 当我这样做时,查询结果会有所不同。

MySQL <5.7 result is 17 rows.

MySQL >5.7 (with Full Group by disabled) result 18 rows.

我的疑问是:

  • 为什么结果集会发生变化,在我的案例中分组依据实际上不应该改变结果。
  • 是否可以在不禁用 FULL GROUP BY 的情况下实现同样的效果?

我阅读了有关 MySQL ANY_VALUE 的信息,但同样它不适用于 SELECT ANY_VALUE(*)

需要有关如何实现上述目标的帮助:) 谢谢

更新 1

本地机器:

SQL 版本 5.7.24

SQL 模式:

STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

有问题的查询:

   SELECT * FROM
   (SELECT h.* FROM testdb h
   WHERE h.date <= '2016-01-02 23:30:00'
   GROUP BY FLOOR(UNIX_TIMESTAMP(h.date)/((1440/2)*60))
   UNION
   SELECT c.* FROM testdb c
   WHERE c.date> '2016-01-02 23:30:00') m;

重现问题的步骤:

CREATE TABLE testdb ( id int primary key auto_increment,date timestamp);


    INSERT INTO testdb (date) VALUES ('2015-12-31 00:00:00');
    INSERT INTO testdb (date) VALUES ('2015-12-31 06:00:00'); 
    INSERT INTO testdb (date) VALUES ('2015-12-31 18:00:00');
    INSERT INTO testdb (date) VALUES ('2016-01-01 00:00:00');
    INSERT INTO testdb (date) VALUES ('2016-01-01 06:00:00');
    INSERT INTO testdb (date) VALUES ('2016-01-01 18:00:00');
    INSERT INTO testdb (date) VALUES ('2016-01-02 00:00:00'); 
    INSERT INTO testdb (date) VALUES ('2016-01-02 06:00:00'); 
    INSERT INTO testdb (date) VALUES ('2016-01-02 18:00:00'); 
    INSERT INTO testdb (date) VALUES ('2016-12-31 00:00:00'); 
    INSERT INTO testdb (date) VALUES ('2016-12-31 06:00:00'); 
    INSERT INTO testdb (date) VALUES ('2016-12-31 06:01:00'); 
    INSERT INTO testdb (date) VALUES ('2016-12-31 12:00:00'); 
    INSERT INTO testdb (date) VALUES ('2016-12-31 18:00:00'); 
    INSERT INTO testdb (date) VALUES ('2017-01-01 00:00:00'); 
    INSERT INTO testdb (date) VALUES ('2017-01-01 06:00:00');
    INSERT INTO testdb (date) VALUES ('2017-01-01 18:00:00');
    INSERT INTO testdb (date) VALUES ('2017-01-02 00:00:01'); 
    INSERT INTO testdb (date) VALUES ('2017-01-02 06:00:00'); 
    INSERT INTO testdb (date) VALUES ('2017-01-02 18:00:00');

查询结果:

18 行

数据库 fiddle

https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=6082783c8a2c8ab1aa5cb5849bfcb06f

SQL 版本 5.7.26

SQL 模式

STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

查询结果:

17 行

最佳答案

这似乎可以满足您的要求:

SELECT COUNT(*)
FROM (SELECT FLOOR(UNIX_TIMESTAMP(h.date)/((1440/2)*60)) FROM testdb h
      WHERE h.date <= '2016-01-02 23:30:00'
      GROUP BY FLOOR(UNIX_TIMESTAMP(h.date)/((1440/2)*60))
      UNION
      SELECT c.date
      FROM testdb c
      WHERE c.date> '2016-01-02 23:30:00'
     ) m;

关于mysql - MYSQL Full GROUP BY 的解决方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56808175/

相关文章:

database - 备份和恢复选项在 pgAdmin III 中不可用

mysql - 从一列中使用 SUM 和 GROUP BY 为另一列选择 MAX,没有子查询

mysql - 如何在MySQL数据库中存储货币符号?

php - 合并多个 POST 并将其添加到表中

mysql - 如何删除超过一定数量的表的所有记录以进行清理

mysql - 如何在我的文本中编写包含不需要空格的查询?

php - 从 PHP 中的单个提交按钮提交两个不同的表单?

c# - 连接字符串在 C# Windows 应用程序中不起作用

mysql - 如何使用 PHPstorm 连接 Openshift Mysql 数据库?

mysql - 值对应于 MYSQL 中的 NOT AT ALL