【问题标题】:How to build a mysql query that checks date and time being between two values?如何构建一个 mysql 查询来检查两个值之间的日期和时间?
【发布时间】:2021-12-19 01:20:00
【问题描述】:

我想构建一个特定的日历功能。

作为地下室,我有以下 MySQL 表:

CREATE TABLE `presence` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `eid` int(10) unsigned DEFAULT NULL,
  `start` timestamp NULL DEFAULT NULL,
  `end` timestamp NULL DEFAULT NULL,
  `frequence` int(11) DEFAULT NULL,
  `fulltime` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

使用以下示例数据:

INSERT INTO `presence` (`id`, `eid`, `start`, `end`, `frequence`, `fulltime`) VALUES (1, 14, "2021-11-29 10:00:00", "2021-12-13 18:00:00", NULL, NULL);
INSERT INTO `presence` (`id`, `eid`, `start`, `end`, `frequence`, `fulltime`) VALUES (2, 14, "2021-11-29 10:00:00", "2021-12-13 18:00:00", 1, NULL);
INSERT INTO `presence` (`id`, `eid`, `start`, `end`, `frequence`, `fulltime`) VALUES (3, 14, "2021-11-29 10:00:00", "2021-12-13 18:00:00", 1, 1);
INSERT INTO `presence` (`id`, `eid`, `start`, `end`, `frequence`, `fulltime`) VALUES (4, 14, "2021-11-29 10:00:00", "2021-12-13 18:00:00", NULL, 1);
INSERT INTO `presence` (`id`, `eid`, `start`, `end`, `frequence`, `fulltime`) VALUES (5, 14, "2021-11-29 10:00:00", NULL, 1, 1);

在我的应用环境中,我有以下示例:

row id#1 表示,从 2021 年 11 月 29 日到 2021 年 12 月 13 日,每天都有员工(eid:14)在场。每天上午 10 点到下午 6 点。

row id#2 表示,从 2021 年 11 月 29 日到 2021 年 12 月 13 日,每个星期一都有一名员工 (eid: 14) 在场。每个星期一上午 10 点到下午 6 点。星期一,因为start 是星期一,因为frequence = 1

row id#3 表示,从 2021 年 11 月 29 日到 2021 年 12 月 13 日,每个星期一都有一名员工 (eid: 14) 在场。每个星期一全天,因为fullday = 1。因此,忽略时间。

row id#4 表示,从 2021 年 11 月 29 日到 2021 年 12 月 13 日,每天都有员工(eid:14)在场。每天一整天,因为fullday = 1 再次告诉忽略时间。

row id#5 终于有了一个开放式的存在。这意味着该员工从 2021 年 11 月 29 日每周一到无限期都在场。

我整天都在处理以下查询,现在我无法说出我的期望......

SET @date = "2021-12-13 19:00:00";
SET @fullday = 0;


SELECT start, end, frequence, fulltime
FROM `presence`
WHERE (
    IF (@fullday = 1, 
        DATE(@date) >= DATE(`start`)
        ,
        DATE(@date) >= DATE(`start`) AND
        TIME(@date) >= TIME(`start`)
    )
)
AND (
    IF (@fullday = 1, 
        DATE(@date) >= DATE(`end`)
        ,
        DATE(@date) >= DATE(`end`) AND
        TIME(@date) >= TIME(`end`)
    )
)
AND (
    `frequence` IS NULL OR
    `frequence` = 1 AND WEEKDAY(@date) = WEEKDAY(`start`)
)

在我的应用程序中,我将有一个 php 函数 employee_is_present(int $eid, string $date): bool,其中 $date 可以是 Y-m-d H:i:s 或只是 Y-m-d,以检查员工是否通常在一天(没有时间)或在a 非常具体的时间。这就是我尝试使用 SET @fullday = 0|1;

模仿的内容

【问题讨论】:

  • 您构建了一个函数,该函数使用 hiur 制作所有日期的序列,以便您拥有一个包含所有工作时间行的临时表,并检查其中是否包含特定日期跨度>

标签: mysql date datetime


【解决方案1】:

根据输入,date可以是有时间也可以没有时间,这两种情况比较容易区分。 我们可以这样做,因为我们使用函数调用来查询

检查日期只能使用这个查询

SET @eid =14; 
SET @date = DATE("2021-12-13");
SELECT *
FROM presence
WHERE @date >= DATE(`start`) AND ( `end` IS NULL OR @date <= DATE(`end`))
AND (`frequence` IS NULL OR (`frequence` = 1 AND WEEKDAY(`start`) = WEEKDAY(@date)))
AND eid = @eid

检查时间,我们使用上面的查询结果并过滤时间

SET @eid =14; 
SET @date = DATE("2021-12-13 19:00:00");
SET @time = TIME(@date);
SELECT *
FROM (
  SELECT *
  FROM presence
  WHERE @date >= DATE(`start`) AND ( `end` IS NULL OR @date <= DATE(`end`))
  AND (`frequence` IS NULL OR (`frequence` = 1 AND WEEKDAY(`start`) = WEEKDAY(@date)))
  AND eid = @eid
) f
WHERE `fulltime` = 1 OR (TIME(`start`) <= @time AND @time <= TIME(`end`))

https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=3e207fed77e34a6b458e79764e382156

【讨论】:

  • 我在您的第一个查询中添加了DATE()。现在它正在工作(在它排除开始日期之前)。但是你的第二个查询给了我零个结果
  • @John Doener,是的,感谢指出错误。
  • 我的意思是,给定的日期和时间 2021-12-13 19:00:00 应该给出零结果,因为 19:00:00 大于 18:00:00
  • @John Doener,在问题中,fullday = 1。因此,忽略时间。,所以我认为 fullday = 1 的行仍然适用
  • @John Doener 第二个查询也遇到了同样的 DATE() 问题,已修复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-05
  • 2021-11-01
  • 1970-01-01
  • 2011-11-10
相关资源
最近更新 更多