A ideia é fazer uma lista de datas únicas de ambas as tabelas primeiro. Então, para cada uma dessas datas, encontre a próxima data (neste caso em particular, as datas são agrupadas por estado, distrito e a próxima data é procurada por determinado estado, distrito).
Então agora temos uma lista de intervalos que estamos procurando. Agora podemos juntar (para esta tarefa específica, join à esquerda) outras tabelas pelas condições exigidas:
select
r.state,
c.start_cong,
c.end_cong,
c.party,
coalesce(c.district, d.district) district,
d.start_dist,
d.end_dist,
start_comb,
end_comb,
case when d.district is not null then start_comb end final_start,
case when d.district is not null then end_comb end final_end
from (
with dates as (
select
*
from (
SELECT
c.state,
c.district,
start_cong date
FROM congressperson c
union
SELECT
c.state,
c.district,
end_cong
FROM congressperson c
union
SELECT
d.state,
d.district,
start_dist
FROM district d
union
SELECT
d.state,
d.district,
end_dist
FROM district d
) DATES
group by
state,
district,
date
order by
state,
district,
date
)
select
dates.state,
dates.district,
dates.date start_comb,
(select
d.date
from
dates d
where
d.state = dates.state and
d.district = dates.district and
d.date > dates.date
order by
d.date
limit 1
) end_comb
from
dates) r
left join congressperson c on
c.state = r.state and
c.district = r.district and
start_comb between c.start_cong and c.end_cong and
end_comb between c.start_cong and c.end_cong
left join district d on
d.state = r.state and
d.district = r.district and
start_comb between d.start_dist and d.end_dist and
end_comb between d.start_dist and d.end_dist
where
end_comb is not null
order by
r.state, coalesce(c.district, d.district), start_comb, end_comb, start_cong, end_cong