Ms Access SQL 计算与某些排除期重叠的天数

MsAccess SQL count days in overlaping periods with some excluding periods

问题:

给定一个 table 给定人的时间段可能(或可能不)重叠并给定另一个 table 排除,我想计算每个人的天数以及不包括重叠天数和排除期的期间。

正如他们所说,一张图片值 1000 个字,所以:

示例场景:

期间 table:

create table periods (
  `id` COUNTER (1,1) PRIMARY KEY,
  `person_id` text(50),
  `start_date` Date,
  `end_date` Date
)

排除期间table:

create table exclusions (
  `start_date` As Date,
  `end_date` As Date
)

还有一些值:

INSERT INTO `periods`(`person_id`, `start_date`, `end_date`)
VALUES('1', CDate('01/09/2014'), CDate('30/09/2014'));

INSERT INTO `periods`(`person_id`, `start_date`, `end_date`)
VALUES('1', CDate('10/10/2014'), CDate('31/10/2014'));

INSERT INTO `periods`(`person_id`, `start_date`, `end_date`)
VALUES('1', CDate('25/09/2014'), CDate('15/10/2014'));

INSERT INTO `periods`(`person_id`, `start_date`, `end_date`)
VALUES('1', CDate('20/11/2014'), CDate('10/12/2014'));

INSERT INTO `periods`(`person_id`, `start_date`, `end_date`)
VALUES('1', CDate('15/11/2014'), CDate('25/11/2014'));

INSERT INTO `exclusions`(`start_date`, `end_date`)
VALUES(CDate('10/09/2014'), CDate('15/09/2014'));

INSERT INTO `exclusions`(`start_date`, `end_date`)
VALUES(CDate('01/12/2014'), CDate('20/12/2014'));

我试过的:

到目前为止,我能够使用此查询检测重叠时间段:

SELECT s1.person_id as person_id, 
    iif(s1.start_date <= s2.start_date, s1.start_date, s2.start_date) As start_date,
    iif(s1.end_date >= s2.end_date, s1.end_date, s2.end_date) As end_date
FROM
  periods As S1 INNER JOIN periods As S2 ON
    s1.person_id = s2.person_id And
    s1.id < s2.id And
    s2.start_date <= s1.end_date And s2.end_date >= s1.start_date

但是有一个问题,结果是:

person_id   start_date   end_date
 1          01/09/2014  15/10/2014
 1          25/09/2014  31/10/2014
 1          15/11/2014  10/12/2014

请注意,第一行和第二行也是重叠的句点。我可以用它自己的结果来执行相同的查询,但感觉很奇怪。

我需要什么:

我现在遇到的其他问题是我不知道如何:

不幸的是,我只能为此使用 MsAccess,所以我不能使用我在谷歌搜索中发现的一些技巧,因此我在这里问。

您可以使用日历 table 来解决这个问题(接下来 'n' 年每天一行)。

create table calendar (
  `id` COUNTER (1,1) PRIMARY KEY,
  `calendar_date` Date
)

insert into calendar values ('2015-01-01')
insert into calendar values ('2015-01-02')
insert into calendar values ('2015-01-03')
insert into calendar values ('2015-01-04')
insert into calendar values ('2015-01-05') ... et cetera

然后:

select distinct calendar_date
from   periods p join calendar c
where  c.calendar_date between p.start_date and p.end_date and
       not exists(select * from exclusions where c.calendar_date between e.start_date and e.end_date)