我想知道为什么这个查询在不同版本的MySQL中显示不同的结果:

https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=409db6dd827acd7bda4ff9723fa108d9

在MySQL 8 fiddle中,不应显示从10:00到10:30的时段,因为表中有10:00到10:30的预约.

MySQL 5.7:

 
CREATE TABLE shifts (
    id int NOT NULL,
    unique_id varchar(255) NOT NULL,
    start_date DATETIME NOT NULL,
    end_date DATETIME NOT NULL,
    PRIMARY KEY (id)
);

CREATE TABLE appointments (
    id int NOT NULL,
    unique_id varchar(255) NOT NULL,
    start_date DATETIME NOT NULL,
    end_date DATETIME NOT NULL,
    shift_id int NOT NULL,
    PRIMARY KEY (id),
    FOREIGN KEY (shift_id) REFERENCES shifts(id)
);

INSERT INTO `shifts` (`id`, `unique_id`, `start_date`, `end_date`)
VALUES
    ('4596', '614fc0c5dab2485bba8cbbd9eb98aa53', '2022-02-28 10:00:00', '2022-03-15 19:00:00');


INSERT INTO `appointments` (`id`, `unique_id`, `start_date`, `end_date`, `shift_id`)
VALUES
    (18382, '1371e41a7cf342bfa279a8b120cc5f43', '2022-02-28 10:00:00', '2022-02-28 10:30:00', 4596),
    (18517, '124baaa1aeab421cb288f2b7c7abe89b', '2022-02-28 10:30:00', '2022-02-28 11:00:00', 4596),
    (18523, 'aff5abe6e8f84a64ace3277d3cd6dbd1', '2022-02-28 11:00:00', '2022-02-28 12:00:00', 4596),
    (18355, 'ec570f9365bb4ad68c7b5ab3b7d9aeea', '2022-02-28 12:00:00', '2022-02-28 12:30:00', 4596),
    (18537, 'e1946add03cd412da357b58c93d58c6e', '2022-02-28 12:30:00', '2022-02-28 13:15:00', 4596),
    (18540, 'e16af8a053594e8b8340ede302398a22', '2022-02-28 13:30:00', '2022-02-28 14:00:00', 4596),
    (18235, 'deac969701ae47f0a78696f12c267475', '2022-02-28 14:00:00', '2022-02-28 14:30:00', 4596),
    (18462, '3270929ae6e546fb824e6d3219917b8e', '2022-02-28 14:30:00', '2022-02-28 16:00:00', 4596),
    (18544, 'd27bc7ba34a74f078966ebe1567d3181', '2022-02-28 16:00:00', '2022-02-28 16:30:00', 4596),
    (18622, '02ca48b35ca3462f9030bcb97ea1dbab', '2022-02-28 16:30:00', '2022-02-28 16:50:00', 4596),
    (18545, '4a49c054e59e4514ae2a521b55a7715c', '2022-02-28 16:50:00', '2022-02-28 17:15:00', 4596),
    (18351, '6a0d56ad43894b60b4f8a289fbbfff73', '2022-02-28 17:30:00', '2022-02-28 18:15:00', 4596),
    (18352, 'accdc12943954ee2bd69ad116c2fef3d', '2022-02-28 18:15:00', '2022-02-28 19:00:00', 4596);


SELECT Available_from, Available_to
  FROM (
    SELECT COALESCE(@lasttime_to, '2022-02-28 10:00:00') AS Available_from, start_date AS Available_to, @lasttime_to := end_date
    FROM (SELECT start_date, end_date
             FROM appointments
             WHERE shift_id = 4596
             AND end_date <= '2022-02-28 19:00:00'
             AND start_date >= '2022-02-28 10:00:00'
             UNION ALL (
               SELECT '2022-02-28 19:00:00', '2022-02-28 19:00:00'
             )
             UNION ALL (
               SELECT '2022-02-28 10:00:00', '2022-02-28 10:00:00'
             )
               ORDER BY start_date 
           ) e
    JOIN (SELECT @lasttime_to := NULL) init) x
    WHERE Available_to > DATE_ADD(Available_from, INTERVAL 14 MINUTE);


结果:

Available_from  Available_to
2022-02-28 13:15:00 2022-02-28 13:30:00
2022-02-28 17:30:00 2022-02-28 17:30:00

MySQL 8.0:

 
CREATE TABLE shifts (
    id int NOT NULL,
    unique_id varchar(255) NOT NULL,
    start_date DATETIME NOT NULL,
    end_date DATETIME NOT NULL,
    PRIMARY KEY (id)
);

CREATE TABLE appointments (
    id int NOT NULL,
    unique_id varchar(255) NOT NULL,
    start_date DATETIME NOT NULL,
    end_date DATETIME NOT NULL,
    shift_id int NOT NULL,
    PRIMARY KEY (id),
    FOREIGN KEY (shift_id) REFERENCES shifts(id)
);

INSERT INTO `shifts` (`id`, `unique_id`, `start_date`, `end_date`)
VALUES
    ('4596', '614fc0c5dab2485bba8cbbd9eb98aa53', '2022-02-28 10:00:00', '2022-03-15 19:00:00');


INSERT INTO `appointments` (`id`, `unique_id`, `start_date`, `end_date`, `shift_id`)
VALUES
    (18382, '1371e41a7cf342bfa279a8b120cc5f43', '2022-02-28 10:00:00', '2022-02-28 10:30:00', 4596),
    (18517, '124baaa1aeab421cb288f2b7c7abe89b', '2022-02-28 10:30:00', '2022-02-28 11:00:00', 4596),
    (18523, 'aff5abe6e8f84a64ace3277d3cd6dbd1', '2022-02-28 11:00:00', '2022-02-28 12:00:00', 4596),
    (18355, 'ec570f9365bb4ad68c7b5ab3b7d9aeea', '2022-02-28 12:00:00', '2022-02-28 12:30:00', 4596),
    (18537, 'e1946add03cd412da357b58c93d58c6e', '2022-02-28 12:30:00', '2022-02-28 13:15:00', 4596),
    (18540, 'e16af8a053594e8b8340ede302398a22', '2022-02-28 13:30:00', '2022-02-28 14:00:00', 4596),
    (18235, 'deac969701ae47f0a78696f12c267475', '2022-02-28 14:00:00', '2022-02-28 14:30:00', 4596),
    (18462, '3270929ae6e546fb824e6d3219917b8e', '2022-02-28 14:30:00', '2022-02-28 16:00:00', 4596),
    (18544, 'd27bc7ba34a74f078966ebe1567d3181', '2022-02-28 16:00:00', '2022-02-28 16:30:00', 4596),
    (18622, '02ca48b35ca3462f9030bcb97ea1dbab', '2022-02-28 16:30:00', '2022-02-28 16:50:00', 4596),
    (18545, '4a49c054e59e4514ae2a521b55a7715c', '2022-02-28 16:50:00', '2022-02-28 17:15:00', 4596),
    (18351, '6a0d56ad43894b60b4f8a289fbbfff73', '2022-02-28 17:30:00', '2022-02-28 18:15:00', 4596),
    (18352, 'accdc12943954ee2bd69ad116c2fef3d', '2022-02-28 18:15:00', '2022-02-28 19:00:00', 4596);


SELECT Available_from, Available_to
  FROM (
    SELECT COALESCE(@lasttime_to, '2022-02-28 10:00:00') AS Available_from, start_date AS Available_to, @lasttime_to := end_date
    FROM (SELECT start_date, end_date
             FROM appointments
             WHERE shift_id = 4596
             AND end_date <= '2022-02-28 19:00:00'
             AND start_date >= '2022-02-28 10:00:00'
             UNION ALL (
               SELECT '2022-02-28 19:00:00', '2022-02-28 19:00:00'
             )
             UNION ALL (
               SELECT '2022-02-28 10:00:00', '2022-02-28 10:00:00'
             )
               ORDER BY start_date 
           ) e
    JOIN (SELECT @lasttime_to := NULL) init) x
    WHERE Available_to > DATE_ADD(Available_from, INTERVAL 14 MINUTE);


结果:


Available_from  Available_to
2022-02-28 10:00:00 2022-02-28 10:30:00
2022-02-28 13:15:00 2022-02-28 13:30:00
2022-02-28 17:15:00 2022-02-28 17:30:00

推荐答案

子查询estart_date排序,这是不确定的,因为可能有多行具有相同的值.

使用MySQL 5.7:

  1. 此子查询的第一行是通过union创建的假查询.它的from_date2022-02-28 10:00:00end_date2022-02-28 10:00:00,这将是下一行的Available_from,因为您的查询使用@lasttime_to.
  2. 下一行是与约会18382相关的一行,该行变为"从2022-02-28 10:00:00到2022-02-28 10:00:00",end_date设置为2022-02-28 10:30:00,这将是下一行的Available_from.
  3. 下一行是与约会18517相关的,它变成了"从2022-02-28 10:30:00到2022-02-28 10:30:00"

所以在这里,这三行都不符合标准Available_to > DATE_ADD(Available_from, INTERVAL 14 MINUTE);

使用MySQL 8:

  1. 这个子查询的第一行是与约会18382相关的,而不是假的.它的from_date2022-02-28 10:00:00end_date2022-02-28 10:30:00,这将是下一行的Available_from,因为您的查询使用@lasttime_to.
  2. 下一行是通过union创建的假行.它变成了"2022-02-28 10:30:00 2022-02-28 10:00:00"(!),它的end_date2022-02-28 10:00:00,这将是下一行的Available_from.
  3. 下一行是与约会18517相关的,它变成了"2022-02-28 10:00:00到2022-02-28 10:30:00".

这里,第三行与标准Available_to > DATE_ADD(Available_from, INTERVAL 14 MINUTE);匹配,这就是为什么会得到一个额外的行.

TL;DR:行的Available_from个值依赖于子查询e获得的非确定性顺序.因此,从一个引擎到另一个引擎的结果并不一致.

Mysql相关问答推荐

SQL条件 Select 和条件WHERE

如何在产品查询中插入GROUP_CONCAT?

如何计算超过特定数字的所有不同ID组,然后返回这些ID?

使用MySQL工作台导出具有数据的数据库表并导入到其字段具有不同数据类型的同一表中

版本升级到5.0.0后在QueryDSL中使用Enum时出错

MySQL中的where语句会 destruct 全外连接.

列出每年最多产的三位作家

使用 SELECT 时应锁定多少行 .. FOR UPDATE LIMIT 1

如何根据购买的商品数量查找 unique_ids 的数量

在 Spring Data jpa 中的 @Query 中无法识别本机查询

为什么这个 NOT NULL 到 NULL 迁移会触发大量 I/O 操作?

由于长时间操作而断开连接后,我的 sql 查询是否继续执行?

MySQL查询以获取日期范围内的租赁订单

插入重复键查询以在每一行上进行自定义更新

MySql 以秒为单位的两个时间戳之间的差异?

如何在 MySQL 中为用户设置默认架构

MySQL Workbench 无法加载 mysql.proc

MySQL错误 1005 (HY000): 无法创建表 'foo.#sql-12c_4' (errno: 150)

在 Mac 上设置 Laravel php artisan migrate 错误:没有这样的文件或目录

邮箱地址可接受的字段类型和大小?