【问题标题】:SQL OVERLAPS how to include the dates of at the extremes?SQL OVERLAPS 如何在极端情况下包含日期?
【发布时间】:2015-07-26 14:49:25
【问题描述】:

如何在 SQL OVERLAPS 中包含开始和结束日期?

喜欢 =。怎么做?

因为在我看来,OVERLAPS 只检查两者之间的范围,但是例如:

2001 年 1 月 1 日 - 2001 年 1 月 5 日的日期已经在数据库中,

我选择 1 月 5 日作为新系列的第一个日期,它对我说这很好。相反,我想要OVERLAPS = true,因为 2001 年 1 月 5 日已经在数据库中,我不能从 1 月 5 日开始新的范围,而是从 1 月 6 日开始。

如何在 OVERLAPS 中包含极端日期?

【问题讨论】:

  • 来自documentationEach time period is considered to represent the half-open interval start <= time < end, unless start and end are equal in which case it represents that single time instant. This means for instance that two time periods with only an endpoint in common do not overlap.
  • @Marth,有解决方案吗?你能帮帮我吗?
  • 我可能会使用@gordonlinoff 的解决方案。另一种方法(也不包括“添加 1 天”~hack)是构造封闭的dateranges,然后使用&& 运算符。但是我没有这些解决方案的任何基准,但如果你有,请分享!
  • @Marth,我不明白你的daterange's 解决方案。你能解释得更好吗?
  • 刚刚发布它作为答案。请询问是否仍有不清楚的地方。

标签: sql postgresql date overlap


【解决方案1】:

您可以使用封闭的dateranges('[]' 参数)和&&(重叠)运算符:

SELECT daterange('2001-01-01', '2001-01-05', '[]') &&
       daterange('2001-01-05', '2001-01-10', '[]');
┌──────────┐
│ ?column? │
├──────────┤
│ t        │
└──────────┘

请注意,使用范围还可以让您访问很多有用的operators

【讨论】:

  • &&OVERLAPS 更具有专有性,并且使用相同的逻辑:-)
  • @dnoeth :嗯,是的,但是你可以关闭而不是半开。不过老实说,我可能还是会选择 Gordon Linoff 的解决方案。
  • 当然你是对的,我忽略了[]。这是一个不错的扩展,但运算符语法真的很神秘......
【解决方案2】:

有趣。我不使用overlaps 有两个原因。第一个是它只在 Postgres 中可用(我不喜欢太习惯于只在一个数据库中可用的构造)。第二个是简单的等式就足够了。

当第一个间隔在第二个结束时或之前开始时,两个间隔重叠并且第一个在第二个开始时或之后结束。这是您想要的逻辑示意图:

where first.start <= second.end and first.end >= second.start

【讨论】:

  • 但如果我只使用 PostfreSQL,也许 OVERLAPS 会更有效?
  • @JohnSam 。 . .这是可能的。如果是这样,您可以从您的范围中添加/减去一天。
  • 我认为减日期的解决方案就像一个黑客,我不会使用它。我需要一个好的解决方案。从OVERLAPS&lt;= 解决方案中高效地进行基准测试会很有趣。如何用大量种子进行测试?
  • 值得注意的是OVERLAPS标准 SQL。
  • @ErwinBrandstetter 。 . .需要注意的是,当其他数据库开始支持它时,我会更倾向于使用它。
【解决方案3】:

标准 SQL 的 OVERLAP 是基于半开周期,即包括开头而排除结尾。

这是来自 ISO 9075 文档:

The result of the <overlaps predicate> is the result of the following expression:
( S1 > S2 AND NOT ( S1 >= T2 AND T1 >= T2 ) )
OR
( S2 > S1 AND NOT ( S2 >= T1 AND T2 >= T1 ) )
OR
( S1 = S2 AND ( T1 <> T2 OR T1 = T2 ) )

这对人类来说有点奇怪,但只要你处理 DATE: 星期一星期三重叠星期三星期五,因为人们假设它是结束结束日期为周三,开始日期为 begin

但是当您切换到 TIMESTAMP 时,情况会发生变化: 星期一早上星期三中午不重叠星期三中午星期五晚上

事实上,使用半开间隔要容易得多,因为下一个周期的开始正好是上一个周期的结束,您不必考虑添加天/秒/毫秒。

多年来,我一直习惯于实现临时表(缓慢变化的维度),它们现在是标准 SQL,并在 Teradata、DB2 和下一版本的 SQL Server 中实现。

所以你应该考虑改变你的实现 :-) 如果你不能,你可以在使用 OVERLAPS 或使用 Gordon 的逻辑之前加/减一天,做对你来说更容易的事情,不要太在意效率。 (我更喜欢第一个,因为 Teradata 在难以重写的时期内支持一些不错的功能)。

【讨论】:

  • 或者我可以从日期中减去分钟(或添加,都是一样的)。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-22
  • 2020-06-09
  • 1970-01-01
  • 2021-09-29
相关资源
最近更新 更多