Как проверить, покрывается ли период времени меньшими периодами в SQL? - PullRequest
0 голосов
/ 01 декабря 2019

Наличие таблиц, подобных следующей:

create table originalPeriods (
    [Id] INT PRIMARY KEY,
    [Start] DATETIME NOT NULL,
    [End] DATETIME NOT NULL,
    [Flag1] INT NOT NULL,
    [Flag2] INT NOT NULL,
    CONSTRAINT UC_UniueFlags UNIQUE (Flag1,Flag2)
)
go

create table convertedPeriods(
    [Id] INT PRIMARY KEY,
    [Start] DATETIME NOT NULL,
    [End] DATETIME NOT NULL,
    [Flag1] INT NOT NULL,
    [Flag2] INT NOT NULL
)
go

Я хочу проверить, представлен ли каждый период из первой таблицы набором периодов из второй таблицы с соответствующими флагами.

Я хочу, чтобы преобразованные периоды (из второй таблицы) заполняли весь исходный период (из первого периода) без пробелов, перекрытий и расширений! Преобразованные периоды должны точно соответствовать исходному периоду.

Идеальным результатом будет список исходных периодов Id с флагом того, хорошо ли он охвачен преобразованными периодами.

Ответы [ 2 ]

1 голос
/ 05 декабря 2019

Попробуйте, дайте мне знать, если это работает:

select
    op.Id
    ,[Flag: Converted Period matches Original Period] = case when cp.Id is not null then 'Found' else 'Not Found' end

from originalPeriods as op
left join convertedPeriods as cp on cp.[Start] = op.[Start] and cp.[End] = op.[End]
0 голосов
/ 11 декабря 2019

Полагаю, вы ищете что-то вроде этого

with RECURSIVE periodsNet as (
    select o.id, o.dtstart, o.dtend,
    c.dtend as netPoint, 
    exists(select * from convertedPeriods c2
     where (c2.dtstart > c.dtstart and c2.dtstart < c.dtend)
     or (c2.dtend > c.dtstart and c2.dtend < c.dtend)
    ) as hasOverlap
    from originalPeriods o
    inner join convertedPeriods c
    on o.dtstart = c.dtstart    
    union all 
    select o.id, o.dtstart as ostart, o.dtend as oend,
    c.dtend as netPoint, 
    exists(select * from convertedPeriods c2
     where (c2.dtstart > c.dtstart and c2.dtstart < c.dtend)
     or (c2.dtend > c.dtstart and c2.dtend < c.dtend)
    ) as hasOverlap
    from periodsNet o
    inner join convertedPeriods c
    on o.netPoint = c.dtstart
),
periodsFilled as (
    select id, dtstart, dtend,
    case when dtend = max(netPoint) then true else false end filled
    from periodsNet
    group by id, dtstart, dtend
)
select *,
exists(select * from periodsNet n where n.id = p.id and n.hasOverlap) as hasOverlap
from periodsFilled p

см. Скрипку> https://www.db -fiddle.com / f / jpezmztvj7uFg1PvixaBsh / 0

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...