如何解决嵌套查询的时间重叠
根据当前架构,我被要求查找
-未经测试并暴露于某种传染病的人 -不要列出任何人两次,也不要列出已知的病人 -曝光=位于同一位置,并且时间重叠(为简单起见,无需重叠时间)
在下面的查询中,我找到了答案,但我无法删除“积极”的人,因为我查询的第二部分(即时间流逝)取决于第一部分,即积极的人去相同地点的时间。 / p>
select * from (
select disTINCT person.PersonID,Register.LociD,Register.Checkin,Register.CheckOut
from person
join Register on Person.PersonID = Register.PersonID
join testing on person.PersonID = testing.PersonID
where testing.Results is 'Positive' ) a
join (
SELECT disTINCT Person.PersonID,Register.CheckOut
from person join Register on Person.PersonID = Register.PersonID
where person.PersonID
not in (SELECT disTINCT testing.PersonID from testing)) b on a.LociD = b.LociD
and b.checkin >= a.CheckIn and b.CheckIn <= a.CheckOut
所以我的问题是,此查询仅需要显示第二部分结果的结果需要做哪些修改?
我认为第一部分是
select * from (
select disTINCT person.PersonID,Register.CheckOut
from person
join Register on Person.PersonID = Register.PersonID
join testing on person.PersonID = testing.PersonID
where testing.Results is 'Positive' ) a
第二部分是
join (
SELECT disTINCT Person.PersonID,Register.CheckOut
from person join Register on Person.PersonID = Register.PersonID
where person.PersonID
not in (SELECT disTINCT testing.PersonID from testing)) b on a.LociD = b.LociD
and b.checkin >= a.CheckIn and b.CheckIn <= a.CheckOut
解决方法
这是一个复杂的查询。因为您不希望重复,所以我建议仅使用exists
对外部查询使用persons
。
让人们同时在同一地方的想法是在register
上使用位置和时间重叠进行自我连接。我认为这是查询中最复杂的部分。剩下的就是检查一个人是否是积极的:
select p.*
from person p
where not exists (select 1
from testing t
where t.personid = p.personId and t.results = 'positive'
) and
exists (select 1
from register r1 join
register r2
on r1.locid = r2.locid and
r1.checkin < r2.checkout and
r2.checkout > r1.checkin join
testing t2
on r2.personid = t2.personid and
t2.results = 'positive' and
t2.timestamp < r2.checkout
where r1.personid = p.personid
);
时间安排有点棘手,但我认为时间安排是有道理的。有人需要在同一个地方测试之前。当然,如果没有时间限制,您可以删除t2.timestamp < r2.checkout
。
出于可读性考虑,您可以创建CTE
,如下所示:
with
-- returns all the untested persons
untested as (select p.* from person p left join testing t on t.personid = p.personid where t.testingid is null),-- returns all the infected persons
infected as (select * from testing where results = 'Positive'),-- returns all the locids that infected persons visited and the start and dates of these visits
loc_positive as (
select r.locid,i.timestamp startdate,r.checkout enddate
from register r inner join infected i
on i.personid = r.personid and i.timestamp between r.checkin and r.checkout
)
-- returns the distinct untested persons that visited the same locids with persons tested positive at the same time after they were tested
select distinct u.*
from untested u
inner join register r on r.personid = u.personid
inner join loc_positive lp on lp.locid = r.locid
where lp.startdate <= r.checkout and lp.enddate >= r.checkin
,
此答案的解决方案是在第一行中为星标添加唯一名称和列名称。
select DISTINCT unt.PersonID from (
select person.PersonID,Register.LocID,Register.Checkin,Register.CheckOut
from person join Register on Person.PersonID = Register.PersonID join testing on person.PersonID = testing.PersonID
where testing.Results is 'Positive' ) pos
join (
SELECT Person.PersonID,Register.CheckOut
from person join Register on Person.PersonID = Register.PersonID where person.PersonID
not in (SELECT testing.PersonID from testing)) unt on pos.LocID = unt.LocID
and unt.checkin >= pos.CheckIn and unt.CheckIn <= pos.CheckOut;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。