【问题标题】:Select between two dates when there is overlapping重叠时在两个日期之间选择
【发布时间】:2021-07-15 07:28:40
【问题描述】:

我的视图中有这些数据

ID       event_start               event_end           
499 2021-07-13 00:00:00.000 2021-07-13 00:00:00.000 
499 2021-07-15 00:00:00.000 2021-07-15 00:00:00.000 
499 2021-07-14 05:00:00.000 2021-07-14 06:00:00.000 
499 2021-07-14 02:00:00.000 2021-07-14 03:00:00.000 
499 2021-07-14 07:00:00.000 2021-07-14 09:00:00.000

所以我有@date_start 和@date_end 的参数,并想像这样选择:

DECLARE @date_start datetime2 = '2021-07-14 07:00', @date_end datetime2 = '2021-07-14 08:10'

Select ID, t1.event_start, t1.event_end from Table1 
WHERE event_start >= @date_start AND event_end <= @date_end
AND ID=499

这不会给我返回结果。但我的目标是获得最后一行。

499 2021-07-14 07:00:00.000 2021-07-14 09:00:00.000

因为这一行从 7 开始,到 9 结束,这将涵盖 @date_start 和 @date_end 期间。我怎么能这样做?

如果我把@date_start 和@date_end 改成这样:

DECLARE @date_start datetime2 = '2021-07-14', @date_end datetime2 = '2021-07-14'

它应该返回

499 2021-07-14 05:00:00.000 2021-07-14 06:00:00.000 
499 2021-07-14 02:00:00.000 2021-07-14 03:00:00.000 
499 2021-07-14 07:00:00.000 2021-07-14 09:00:00.000

因为这三行都发生在同一天,只是时间不同。

谢谢

【问题讨论】:

  • 当您实际上希望给定范围落入行范围时,您当前正在要求行范围落入给定范围内。因此:WHERE @date_start &gt;= event_start AND @date_end &lt;= event_end 如果我没记错的话。
  • 是的,在一种情况下有效。但是当我的 start_date 和 end_date 没有时间时,它在第二种情况下不起作用。
  • 正确。这不适用于第二个示例,因为给定的范围表示午夜(没有时间的日期被解释为 00:00:00)。如果给定的范围是一整天(00:00 - 23:59'),那么任何行都不会覆盖该范围。
  • 我认为您必须准确定义要应用的规则,因为显然有时您想要覆盖的范围,而其他时候则不需要。似乎如果给出了两个日期时间(即两者中至少有一个的时间 > 00:00?),那么给定的范围必须完全适合行范围。如果只给出日期(没有时间部分或时间 = 00:00),那么行范围必须至少包含两个给定日期中的每一个日期的一秒?把规则定义准确,然后一步步放到SQL里面。
  • 不清楚是希望参数中的日期范围在表格中的日期范围内,还是希望表格中的日期范围在参数范围内,还是希望表中与参数重叠(甚至部分重叠)的任何日期范围。这是三种不同的东西,要清楚自己想要哪一种。

标签: sql sql-server tsql


【解决方案1】:

您似乎确实想检查表中的日期范围是否与参数中指定的日期范围重叠。

假设两个间隔是否相互对接并不重要(比如 07:00-08:00 和 08:00-09:00),您需要像这样进行间隔检查 @ 987654321@

DECLARE @date_start datetime2 = '2021-07-14 07:00', @date_end datetime2 = '2021-07-14 08:10'

SELECT
    ID,
    t1.event_start,
    t1.event_end
FROM Table1 
WHERE event_start < @date_end AND event_end > @date_start
  AND ID = 499;

【讨论】:

  • 这很有帮助。在没有时间的情况下对 date_end 进行一些操作,我能够实现这两种情况。 SET new_date_end = DATEADD(MINUTE, DATEDIFF(MINUTE, date_end, DATEADD(DAY, 1, date_end)) -1 , date_end)
  • 如果您能提供帮助,我遇到了一个问题。如果我的表中有这些数据。 499 2021-07-15 00:00:00.000 2021-07-15 00:00:00.000。 DECLARE date_start datetime2 = '2021-07-15', date_end datetime2 = '2021-07-15' 在我更改 event_end >= @date_start 之前不会返回任何内容
  • 但如果我这样更改,我将无法在 07:00-08:00 和 08:00-09:00 进行预订,因为它会说有预订。看来我可以两者兼得。
  • 我想这完全取决于您如何定义间隔。我个人会说没有时间的间隔不能重叠任何东西,但是是的,你的改变是一个有效的选择。
  • 有什么方法可以同时实现吗? event_end > date_start 允许我在 07:00-08:00 和 08:00-09:00 进行预订,但不会在 2021-07-15 至 2021-07-15 接机。 event_end >= date_start 将返回 2021-07-15 到 2021-07-15。但无法在 07:00-08:00 和 08:00-09:00 预订。
【解决方案2】:

首先要记住,您的日期时间是 DATETIME 类型吗?

如果是这样,让我们​​检查第一种情况。

1.要查看日期时间/时间戳是否包含在范围内,我们指定以下 WHERE 子句:

WHERE 
  event_start <= '2021-07-14 07:00:00' and
  event_end >= '2021-07-14 08:10:00'

1.输出

id  event_start             event_end
--- ----------------------- -----------------------
499 2021-07-14 07:00:00.000 2021-07-14 09:00:00.000

如果您的数据不是 DATETIME/TIMESTAMP 类型,这可能不起作用。

2.在这里,你改变了条件,因为你想要一整天发生的所有事情。因此,WHERE 子句如下所示:

WHERE 
  event_start >= '2021-07-14' and
  event_end < '2021-07-15'

2。输出

id  event_start             event_end
--- ----------------------- -----------------------
499 2021-07-14 05:00:00.000 2021-07-14 06:00:00.000
499 2021-07-14 02:00:00.000 2021-07-14 03:00:00.000
499 2021-07-14 07:00:00.000 2021-07-14 09:00:00.000

希望对您有所帮助!

【讨论】:

  • 谢谢,是的,它们是 datetime2 格式。所以这不应该是一个问题。我的主要目的是检查我的数据库,看看用户选择的开始日期和结束日期是否会与任何现有的预订发生冲突。有没有办法用我给你看的数据做到这一点?
  • 例如,如果 DECLARE date_start datetime2 = '2021-07-14 07:00', date_end datetime2 = '2021-07-14 08:10',那么我不允许从 7 开始再次预订到 8 点,因为它将与从 7 点到 9 点的现有预订重叠。如果有人想在 2021 年 7 月 14 日预订一整天,这也是不可能的,因为已经有预订。如果是6点到7点订的话应该没问题。
  • 您的问题的要点已经得到解答。您不应该考虑发布另一个问题,确切地询问您在这里告诉我的内容吗?
猜你喜欢
  • 2017-01-17
  • 1970-01-01
  • 2021-01-18
  • 2017-03-07
  • 2015-07-08
  • 1970-01-01
  • 1970-01-01
  • 2018-03-03
  • 1970-01-01
相关资源
最近更新 更多