Consider the following tables:
create table `t1` (
`date` date,
`value` int
);
create table `t2` (
`date` date,
`value` int
);
create table `t3` (
`date` date,
`value` int
);
insert into `t1` (`date`, `value`)
values ("2022-01-01", 1),
("2022-03-01", 3),
("2022-04-01", 4);
insert into `t2` (`date`, `value`)
values ("2022-01-01", 1),
("2022-02-01", 2),
("2022-04-01", 4);
insert into `t3` (`date`, `value`)
values ("2022-01-01", 1),
("2022-02-01", 2),
("2022-03-01", 3);
The t1
table is missing 2022-02-01
date and t2
is missing 2022-03-01
and t3
is missing 2022-04-01
. I want to join these three tables so that it produces the following result:
| t1.date | t1.value | t2.date | t2.value | t3.date | t3.value |
| | | | | | |
| 2022-01-01 | 1 | 2022-01-01 | 1 | 2022-01-01 | 1 |
| null | null | 2022-02-01 | 2 | 2022-02-01 | 2 |
| 2022-03-01 | 3 | null | null | 2022-03-01 | 3 |
| 2022-04-01 | 4 | 2022-04-01 | 4 | null | null |
I know how to do full outer join
with two tables but with three or more tables things are more complicated. I’ve tried queries like this but it didn’t produce the result I want:
select *
from `t1`
left join `t2` on `t2`.`date` = `t1`.`date`
left join `t3` on `t3`.`date` = `t2`.`date` or `t3`.`date` = `t1`.`date`
union
select *
from `t1`
right join `t2` on `t2`.`date` = `t1`.`date`
right join `t3` on `t3`.`date` = `t2`.`date` or `t3`.`date` = `t1`.`date`;
6
Answers
I achieved the result I wanted with a different approach:
You are on right track but you have to consider all combinations – 3 tables – 4 union clauses.
I am not sure what are you trying to do; the left join is used to keep all the rows from your left table and bring all the matching rows from your right table.
It means: since you do not have the ‘2022-02-01’ date in the t1 it will never appear in your query by using a left join.
Now if you want to combine all the results from three tables, a union between the three tables will do the trick:
select *
from t1
union
select *
from t2
union
select *
from t3;
If you want it ordered just make a subquery:
select *
from (
select *
from t1
union
select *
from t2
union
select *
from t3
) as allData
order by
date
;I hope it helps.
This is it:
http://sqlfiddle.com/#!9/0fbc85/9
This is only concerned for these three tables only..
You also would need to create a date range table for all the ranges presenting in the dates present in all the tables!!!
You can do (t1 full join t2) full join t3 with a full join implementation of choice. Provided joining on primary keys so duplicates must be excluded
db-fiddle
First you have to UNION ALL dates from all three tables. Then you sort and distinct this union, and finally you left join all three tables consequently.
In your last solution I am still missing DISTINCT and ORDER BY.
This should do the result you wanted: