【问题标题】:Check if event is before, after or during other event检查事件是在其他事件之前、之后还是期间
【发布时间】:2012-06-13 12:26:11
【问题描述】:

我被代码卡住了。我想查看来自 MySQL 数据库的女巫事件是在输入事件之前、之后和期间。

我有一个包含以下字段的表格:

  • Event_id (int AUTO_INCREMENT)
  • start_date(日期)
  • start_time (varchar)
  • end_date(日期)
  • end_time (varchar)

开始时间和结束时间都是24小时制,存储时不带冒号:(所以23:50存储为2350,1:00存储为0100)

输入事件的日期和时间将采用相同的格式。

如何进行查询(或脚本)以获取最接近输入事件的事件、检查输入事件期间是否存在事件的查询以及获取在输入事件之后最接近的事件的查询?

【问题讨论】:

  • 您为什么不使用TIMEDATETIME 格式?
  • 为什么不只为开始/结束日期设置 2 个日期和时间列?
  • 您应该使用TIMESTAMPDATETIME 将日期和时间存储在一起。在这种情况下,TIMESTAMP 似乎是最好的解决方案。
  • 好的,谢谢。所以如果我使用 TIMESTAMP,查询会是什么样子?

标签: php mysql date time


【解决方案1】:

首先,从改变你的方案开始,这样你就有了

event_id (int AUTO_INCREMENT),
start_date (timestamp), 
end_date (timestamp)

对于您的查询,您现在可以使用TIMEDIFF

最近的活动

SELECT *, TIMEDIFF(input_date, start_date) diff
FROM events ORDER BY diff LIMIT 1

这将为您带来下一个活动。

活动期间的活动

SELECT * FROM events
WHERE
  TIMEDIFF(input_date, start_date) > 0 AND
  TIMEDIFF(input_date, end_date) < 0
FROM events

这将为您提供正在进行的活动。

在进行比较之前,您可能需要将 TIMEDIFFs 包装在 SECONDS() 中。

【讨论】:

  • 非常感谢!我只对最近的事件查询做了一个小的调整。 SELECT *, TIME_TO_SEC(TIMEDIFF(input_date, start_date)) diff FROM events WHERE TIME_TO_SEC(TIMEDIFF('input_date', end_date)) > 0 ORDER BY diff LIMIT 1 因为否则你也会得到负值(事件发生在事件之前或之前)
【解决方案2】:

要实现这一点,您确实需要将 DATE + VARCHAR 字段转换为更合适的字段,例如 DATETIME(我更喜欢 datetime,它在查询时更具可读性,并且在内部与时间戳一样快)

然后将 4 个字段合并为 2 个字段后,您可以使用两种类型的查询:

SELECT
    CASE 
        WHEN startDateTime <= "targetDate" AND endDateTime > "targetDate" THEN "while"
        WHEN startDateTime > "targetDate" THEN "before"
        WHEN endDateTime <= "targetDate" THEN "after"
    END AS timeframe,
    events.*
FROM
    events

或者你也可以使用联合,两者都会产生相似的结果,选择你喜欢的一个:

SELECT "before" AS timeframe, events.* FROM events
WHERE startDateTime > "targetDate"
UNION
SELECT "while" AS timeframe, events.* FROM events
WHERE startDateTime <= "targetDate" AND endDateTime > "targetDate"
UNION
SELECT "after" AS timeframe, events.* FROM events
WHERE endDateTime <= "targetDate"

PS:我没有测试过,但想法是对的,你可能需要适应它。

祝你好运

【讨论】:

  • 您不应该在 DATETIME 和 TIMESTAMP 之间进行选择,具体取决于 看起来 更好。 DATETIME 是一种非常简单的类型,它只存储在日历中找到的日期和在时钟上找到的时间,其中 TIMESTAMP 存储时间点。也就是说,时区等在存储时会被考虑在内。这不是 DATETIME 的情况 - 这两种类型有完全不同的应用程序!在这种情况下,没有理由使用 DATETIME。
  • 很高兴你拆毁我的帖子,说我不应该选择看起来更好的时间。我想这是一个观点,但出于这个简单的原因,我不喜欢使用 TIMESTAMP,当我选择数据并制作报告时,我想查看我的日期。关于 TZ,您通常不应该将 TZ 存储在数据库中,而是将所有内容标准化为 GMT+0 或 UTC,然后使用用户的 TZ 来调整输出。嗯,这就是我的观点,有数百万种方法可以到达那里。
  • 我不是在拆除任何东西,我是在批评。关于时区,TIMESTAMP 会自动将所有内容转换为 UTC 进行存储。手动执行此操作似乎是多余的。您应该在视图中或程序的其他位置格式化您的报告。 SQL 数据不适合直接展示。
  • 顺便说一下,DATETIME 没有您声称的 TIMESTAMP 快。它们使用两倍的空间,并且不能在内部缓存。
  • 我仍在尝试找出您在哪里看到 DATETIME 比 TIMESTAMP 慢,因为我一直在网上看到帖子和测试声称时间戳比 datetime 慢,前提是它们支持的时间更少日期(不能低于 1970 年),在谷歌上查找时间戳与日期时间 mysql 性能,他们都这么说,这是我发现有趣的许多例子之一:gpshumano.blogs.dri.pt/2009/07/06/…
【解决方案3】:

最近的:

Select * from Event_table where start_date<=[imputed start_date] and start_time<[imputed start_time] order by start_date DESC, start_time DESC LIMIT 1

该sql获取插补事件之前的事件列表,按天降序和开始时间降序排序,使第一个结果最接近,LIMIT 1只恢复1条记录,最接近之前。

也许您更喜欢按 end_date 和 end_time(而不是 start_date 和开始时间)过滤以获得事件的最近结束。

在将 [imputed start_date] 和 [imputed start_time] 更改为 end_date 和 end_time 以及 '' 后获得最接近的值

要获取估算事件期间的事件数,请使用简单查询:

Select count(event_id) from event_table where ( start_date between ([imputed start_date] and [imputed end_date]) or end_date between ([imputed start_date] and [imputed end_date]) ) AND (start_time between ([imputed start_time] and [imputed end_time]) OR (end_time between ([imputed start_time] and [imputed end_time]))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-08
    • 1970-01-01
    • 1970-01-01
    • 2018-11-23
    • 1970-01-01
    相关资源
    最近更新 更多