【问题标题】:Ranges of dates overlapping日期范围重叠
【发布时间】:2012-08-03 13:44:33
【问题描述】:

我有两个包含日期的变量。 DateStartDateEnd(在 SQL 中)。
我还有两个 DatePicker 控件(在 WinForm 中)。
我从数据库中导入了两个日期,需要做一些棘手的事情。

因此,这两个变量创建了一个日期范围,而两个日期选择器创建了另一个日期范围。
如何检查这些日期范围是否与 Sql 查询重叠?

例如(yyyy/mm/dd 格式)

DateStart = 2012/07/01, DateEnd = 2012/07/31

| DatePicker1  | DatePicker2 | Overlapping | 
--------------------------------------------
| 2012/07/15   | 2012/07/16  |    True     |
--------------------------------------------
| 2012/07/31   | 2012/08/01  |    True     |
--------------------------------------------
| 2012/06/20   | 2012/07/01  |    True     |
--------------------------------------------
| 2012/08/01   | 2012/09/01  |    False    |
--------------------------------------------

我知道这有点搞砸了,但我不知道还能问这个问题。

【问题讨论】:

    标签: c# sql-server-2008 date-range


    【解决方案1】:

    如果第一个范围的开始在第二个范围的结束之前并且第一个范围的结束在第二个范围的开始之后,则两个日期范围重叠。所以:

    where DateStart <= @DatePicker2
      and DateEnd >= @DatePicker1
    

    A good explanation is this way.

    【讨论】:

      【解决方案2】:

      使用此功能

      /* 
       * Tests if two given periods overlap each other.
       *
       * @TS Test period start
       * @TE Test period end
       * @BS Base period start
       * @BE Base period end
       */
      CREATE FUNCTION [fn_DateTime_Overlap]
      (
          @TS DATETIME = NULL,
          @TE DATETIME = NULL,
          @BS DATETIME = NULL,
          @BE DATETIME = NULL
      )
      RETURNS BIT
      AS
      BEGIN
          -- More simple?
          -- return !((TS < BS && TE < BS) || (TS > BE && TE > BE));
          -- The version below, without comments 
          -- (TS >= BS && TS < BE) || (TE <= BE && TE > BS) || (TS <= BS && TE >= BE)
          IF (
              -- 1. Case:
              --       TS-------TE
              --    BS------BE
              -- TS is after BS but before BE
              (@TS >= @BS AND @TS < @BE)
              -- 2. Case
              --    TS-------TE
              --        BS---------BE
              -- TE is before BE but after BS
              OR (@TE <= @BE AND @TE > @BS)
              -- 3. Case
              --  TS----------TE
              --     BS----BE
              -- TS is before BS and TE is after BE
              OR (@TS <= @BS AND @TE >= @BE)
          ) RETURN 1
          RETURN 0
      END
      

      【讨论】:

      • 令人印象深刻。不过我更喜欢紧凑版:-P