如何在MySQL中使用三个表进行FULL OUTER JOIN?

vlf7wbxs  于 2023-06-21  发布在  Mysql
关注(0)|答案(6)|浏览(137)

考虑以下表格:

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);

t1表缺少2022-02-01日期,t2缺少2022-03-01t3缺少2022-04-01。我想连接这三个表,以便产生以下结果:

| 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     |

我知道如何用两个表来做full outer join,但是用三个或更多的表,事情就更复杂了。我尝试过这样的查询,但它没有产生我想要的结果:

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`;
ttisahbt

ttisahbt1#

你走在正确的轨道上,但你必须考虑所有的组合-3个表-4个联合条款。

-- t1 full join with t2
select *
from `t1`
left join `t2` on `t2`.`date` = `t1`.`date` 
union 
select *
from `t1`
right join `t2` on `t2`.`date` = `t1`.`date` 

-- t1 full join with t3
union 
select *
from `t1`
left join `t3` on `t3`.`date` = `t1`.`date` 

union 
select *
from `t1`
right join `t3` on `t3`.`date` = `t1`.`date`
xwbd5t1u

xwbd5t1u2#

我不知道你想干什么左连接用于保留左表中的所有行,并从右表中获取所有匹配的行。
这意味着:由于t1中没有'2022-02-01'日期,因此使用左连接时它永远不会出现在查询中。
现在,如果你想合并三个表的所有结果,三个表之间的联合就可以做到这一点:
select * from t1 union select * from t2 union select * from t3;
如果你想让它有序,只需做一个子查询:
select * from(select * from t1 union select * from t2 union select * from t3)as allData order by date ;
希望能帮上忙。

brvekthn

brvekthn3#

我用不同的方法实现了我想要的结果:

select 
  t1.date,
  t1.value,
  t2.date,
  t2.value,
  t3.date,
  t3.value
from (
  select t1.date from t1
  union
  select t2.date from t2
  union
  select t3.date from t3
) t
left join t1 on t1.date = t.date
left join t2 on t2.date = t.date
left join t3 on t3.date = t.date;
hgtggwj0

hgtggwj04#

您可以使用选择的完全连接实现来执行(t1完全连接t2)完全连接t3。在主键上提供了连接,因此必须排除重复项

with t12 as (
    select coalesce(t2.`date`, t1.`date`) 'date', t1.`date` t1date, t1.`value` t1val ,t2.`date` t2date, t2.`value` t2val
    from t1
    left join t2 on t2.`date` = t1.`date` 
    union
    select coalesce(t2.`date`, t1.`date`) 'date', t1.`date` t1date, t1.`value` t1val ,t2.`date` t2date, t2.`value` t2val
    from t1
    right join t2 on t2.`date` = t1.`date`     
)
select coalesce(t12.`date`, t3.`date` ) d, t1date, t1val ,t2date, t2val, t3.`date` t3date, t3.`value` t3val 
from t12
left join t3 on t12.`date` = t3.`date` 
union
select coalesce(t12.`date`, t3.`date` ) d, t1date, t1val ,t2date, t2val, t3.`date` t3date, t3.`value` t3val 
from t12
right join t3 on t12.`date` = t3.`date` 
order by d

db-fiddle

3lxsmp7m

3lxsmp7m5#

这就是:

select a.`date`,a.value,a2.`date`,a2.value,a3.`date`,a3.value
from  date_range b left join `t1` a 
on  a.`date`=b.dates
left join `t2` a2
on a2.`date`=b.dates
left join `t3` a3
on a3.`date`=b.dates;

http://sqlfiddle.com/#!9/0fbc85/9
这只涉及这三个表。您还需要创建一个日期范围表,用于所有表中出现的日期中出现的所有范围!!!

z9gpfhce

z9gpfhce6#

首先,你必须联合所有三个表中的所有日期。然后对这个联合进行排序和区分,最后将所有三个表都连接起来。
在你的最后一个解决方案中,我仍然缺少DISTINCT和ORDER BY。
这应该会得到你想要的结果:

Select * From
(
Select distinct `date` From (
Select distinct `date` From t1
Union All
Select distinct `date` From t2
Union All
Select distinct `date` From t3 ) f
Order By f.`date`
) a
LEFT JOIN t1 ON t1.`date` = a.`date`
LEFT JOIN t2 ON t2.`date` = a.`date`
LEFT JOIN t3 ON t3.`date` = a.`date`

相关问题