我有一张包含以下数据的表
PKey Start End Type
==== ===== === ====
01 01/01/2010 14/01/2010 S
02 15/01/2010 31/01/2010 S
03 05/01/2010 06/01/2010 A
想获得以下结果
PKey Start End Type
==== ===== === ====
01 01/01/2010 14/01/2010 S
03 05/01/2010 06/01/2010 A
关于从哪里开始的任何想法?我所做的很多阅读建议我需要创建条目,并且每天都要加入匹配日,这是唯一的方法吗?
答案 0 :(得分:36)
如果您已经有每天应该有效的条目,但是如果您没有这样的开销很重要,并且如果经常使用该查询,则会影响性能。
如果数据采用这种格式,您可以使用简单的日期算法检测重叠,因为重叠只是在给定间隔后开始但在给定完成之前的一个间隔,如
select dr1.* from date_ranges dr1
inner join date_ranges dr2
on dr2.start > dr1.start -- start after dr1 is started
and dr2.start < dr1.end -- start before dr1 is finished
如果你需要特别处理完全在另一个区间内的区间,或者你需要合并区间,即
PKey Start End Type
==== ===== === ====
01 01/01/2010 20/01/2010 S
02 15/01/2010 31/01/2010 S
产生
Start End Type
===== === ====
01/01/2010 31/01/2010 S
你需要更复杂的计算。
根据我对这类问题的经验,一旦你掌握了如何进行计算,就很容易将其转移到SQL中:)
答案 1 :(得分:4)
当我需要比较SQL中的两个时间跨度以进行重叠时,以下是我能想到的四种情况:
这是我为捕获这些场景而创建的OR语句(在我的例子中是Oracle SQL):
and (
s1.start between s2.start and s2.end
OR
s1.end between s2.start and s2.end
OR
s2.start between s1.start and s1.end
)
答案 2 :(得分:2)
select A.*
from MyTable A
inner join MyTable B
on (B.start <= A.end)
and (B.end >= A.start)
或类似的东西(假设日期不可为空,相等的日期算作重叠)。
答案 3 :(得分:2)
也许:
SELECT A.PKey, A.Start, A.End, A.Type
FROM calendar AS A, calendar AS B
WHERE (p.pkey<>a.pkey
AND b.start>=a.start
AND b.end<=a.end)
OR (b.pkey<>a.pkey
AND b.start<=a.start
AND b.end>=a.end)
答案 4 :(得分:1)
我必须做一个非常类似的事情,以阻止重复的假期被输入表格。它在访问中并写入输入的temptable,因此必须在VBA SQL中查询它:
stCommandText = "SELECT " _
& "* " _
& "FROM " _
& "TableName a, " _
& "TableName b " _
& "WHERE " _
& "a.ID = b.ID " _
& "AND a.Startdate >= b.Startdate AND a.StartDate <= b.EndDate " _
& "AND a.AutoNo <> b.AutoNo "
答案 5 :(得分:1)
在我们的查询中,我们都需要这种重叠谓词已经有一段时间了,我想我找到了一个非常简单的解决方案here。
在我的应用程序中,作为一个例子,我的政策具有相同的政策编号,但政策说明可能会从一个会计年度更改为下一个会计年度。当用户输入新记录(相同的策略号,不同的策略描述)时,我需要一种方法来判断该策略是否已存在指定的时间范围。如果新的策略生效/到期日期与数据库中已有的任何内容重叠,我需要将错误输出并告诉用户他们的输入不正确的原因。
为此,我使用了以下谓词:
AND @_expiration >= EffectiveDate AND ExpirationDate >= @_effective
希望其他人认为这和我一样有用。
答案 6 :(得分:0)
在MySQL中你基本上需要:
SELECT COUNT(*)
FROM date_ranges AS A, date_ranges AS B
WHERE A.id <> B.id
AND A.id > B.id
AND A.end_at > B.start_at
AND B.end_at > A.start_at
>
可以替换为>=
以跟随包含匹配。
这个主题与“艾伦的区间代数”有关,关于这方面的更多内容可以通过这些链接找到:
答案 7 :(得分:0)
顺便说一句 - 如果您没有唯一的ID,那么您可以这样做的日期是oracle..FYI
with date_ranges
as
(
SELECT
rownum as pkey,
date_ranges.*
FROM date_ranges
)
select
dr1.*
from
date_ranges dr1 , date_ranges dr2
where dr1.pkey > dr2.pkey
AND dr1.end_dt >= dr2.start_dt
AND dr2.end_dt >= dr1.start_dt
答案 8 :(得分:0)
Sql ='SELECT task_id
,task_start_date
,task_due_date
FROM(wba_task
)WHERE(task_start_date
&lt; =“2016-07-13”AND task_due_date
&gt; =“2016-07-25”)或(task_due_date
BETWEEN“2016-07-13”和“2016-07-25”)';
Codeigniter查询如下。
$fromdaysDate="2016-07-13";//changed date
$todaysDate="2016-07-25";//changed date
$this->db->select('task_id,task_start_date, task_due_date');
$this->db->where('task_start_date <="'.date('Y-m-d', strtotime($fromdaysDate)).'"');
$this->db->where('task_due_date >="'.date('Y-m-d', strtotime($todaysDate)).'"');
$this->db->or_where('task_due_date BETWEEN "'. date('Y-m-d', strtotime($fromdaysDate)). '" and "'. date('Y-m-d', strtotime($todaysDate)).'"');
$alltask=$this->db->get('wba_task')->result_array();
echo $this->db->last_query();
答案 9 :(得分:0)
如果您使用的是 PostgreSQL,只需使用内置的 overlap 运算符
SELECT (DATE '2021-01-01', DATE '2021-04-09')
OVERLAPS (DATE '2021-01-20', DATE '2021-02-10');