Вам нужно FULL OUTER JOIN
s, чтобы иметь дело со случаями, когда таблицы содержат несовпадающие даты.Поскольку MySQL не реализует их, вам нужно объединить LEFT JOIN
и RIGHT JOIN
для их моделирования.
В MySQL 8.x вы можете сделать:
with
l (dt, a, b) as (
select a.dt, a.val, b.val from a left join b on b.dt = a.dt
union
select b.dt, a.val, b.val from a right join b on b.dt = a.dt
),
r (dt, c, d) as (
select c.dt, c.val, d.val from c left join d on c.dt = d.dt
union
select d.dt, c.val, d.val from c right join d on c.dt = d.dt
)
select l.dt, l.a, l.b, r.c, r.d from l left join r on r.dt = l.dt
union
select r.dt, l.a, l.b, r.c, r.d from l right join r on r.dt = l.dt
Результат:
dt a b c d
---------- ------ ------ ------ ------
2019-09-15 60 61 62 63
2019-09-16 140 null null null
2019-09-17 null 141 null null
2019-09-18 null null 142 null
2019-09-19 null null null 143
Для справки, скрипт данных для проверки:
create table a (dt date, val int);
create table b (dt date, val int);
create table c (dt date, val int);
create table d (dt date, val int);
insert into a (dt, val) values ('2019-09-15', 60), ('2019-09-16', 140);
insert into b (dt, val) values ('2019-09-15', 61), ('2019-09-17', 141);
insert into c (dt, val) values ('2019-09-15', 62), ('2019-09-18', 142);
insert into d (dt, val) values ('2019-09-15', 63), ('2019-09-19', 143);
В этом сценарии все таблицы содержат данные для 2019-09-15
, но не для других дат.Тем не менее, запрос объединяет их успешно.
Как примечание: если бы было реализовано FULL OUTER JOIN
, запрос был бы намного короче.Например, в PostgreSQL вы должны написать:
select coalesce(a.dt, b.dt, c.dt, d.dt), a.val, b.val, c.val, d.val
from a
full outer join b on b.dt = a.dt
full outer join c on c.dt = coalesce(a.dt, b.dt)
full outer join d on d.dt = coalesce(a.dt, b.dt, c.dt)