繁体   English   中英

日期范围设置操作

[英]Date range set operations

我在一系列带有各种相关表的SQLite数据库中获得了一些数据。 每个表都有一个开始和结束日期列,表示每个记录有效的日期范围。 SQLite数据库主要使用C#和System.Data.SQLite库进行访问。

我希望能够查询诸如日期范围重叠或不重叠的联接。 我发现加入数据时它们的重叠非常简单:

SELECT a.field, max(a.start, b.start) as start, min(a.end, b.end) as end
FROM a
INNER JOIN b
ON a.field = b.field AND NOT(a.start > b.end OR b.start > a.end);

但我不知道如何获得没有匹配b的时间段。 在没有重叠的地方获取记录很容易:

SELECT a.field, a.start, a.end
FROM a
LEFT JOIN b
ON a.field = b.field AND NOT(a.start > b.end OR b.start > a.end)
WHERE b.field is NULL;

但是它们重叠的位置,或者b分成两个记录呢? 将日期范围显示为时间轴,如何在下面显示的ab=c关系中得到c (这些行代表表ab中各个记录的日期范围,以及结果集c

a: |-----------------|    |--------|  |--------||-----|
b:        |---|                  |--------|
c: |-----|     |-----|    |-----|          |---||-----|

或者更好的是,是否有一些我不知道的库,扩展,命令,或其他可用于简化这些查询的解决方案? 能为我处理凌乱日期范围操作的东西吗?

几个指针:

  • 确保您的值是基于UTC的时间戳,或仅是整个日历日期。 这是为了避免时区和夏令时问题。

  • 使用半开间隔, [start, end) 这将避免两个相邻范围包含相同值的问题。 换一种说法:

    • start <= value < end
    • start <= value && end > value

  • 您可以考虑使用Noda Time 它有一个代表这个井的Interval类型。 但是,它目前没有定义很多操作。

  • 您还可以考虑使用.NET时间段库 ,它定义了大量操作。 请注意,与其.Kind使用的所有DateTime值都具有DateTimeKind.Utc作为其.Kind值。 如果您尝试使用本地种类,它将无法正常运行。 换句话说,不要传递DateTime.Now

  • 当然,没有必要使用任何库。 您始终可以定义自己的结构或类来包含范围。 没有内置任何东西,没有。

  • 您编写的查询适用于检测重叠,但您可能希望稍微简化它:

    而不是: NOT(a.start > b.end OR b.start > a.end)
    这样做: a.start < b.end AND b.start < a.end

    这在逻辑上是等价的,但作为查询会稍微好一点。

我不知道如何直接回答你的问题。 你问的问题并不十分清楚。 具体来说,在最后一个例子中,表中是否已存在两个c范围并且您想要返回它们? 或者你想从a和b之间的计算中构造它们? 如果是后者,最好在C#中执行该部分,而不是在SQL中执行。

使用.NET时间段可以将时间段读入集合,并应用TimeGapCalculatorTimePeriodCombinerTimePeriodSubtractor实用程序来评估所需的间隙和重叠。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM