简体   繁体   English

在MySQL中完全外部联接三个表

[英]Full Outer Join three tables in MySQL

I have following tables and desired output. 我有下表和所需的输出。 I tried like full join based on value and group by subject but its still not showing the desired output 我试过像基于值和按主题分组的完全连接,但它仍未显示所需的输出

Any help or guidance will be much appreciated. 任何帮助或指导将不胜感激。 Below is the MySql query: 下面是MySql查询:

select t1.*,t2.value from Table1 as t1 left join Table2 as t2
on RIGHT(t2.value,1) =RIGHT(t1.value,1) 

union all 
select t1.*,t2.value from Table1 as t1 right join Table2 as t2
on RIGHT(t2.value,1) =RIGHT(t1.value,1)

DDL: DDL:

CREATE TABLE Table1 (`subject` varchar(30), `value` varchar(30));
CREATE TABLE Table2 (`subject` varchar(30), `value` varchar(30));
CREATE TABLE Table3 (`subject` varchar(30), `value` varchar(30));

INSERT INTO Table1
(`subject`, `value`)
VALUES
('subject1', 'ValueA1'),
('subject1', 'ValueA2'),
('subject1', 'ValueA3'),
('subject2', 'ValueA4'),
('subject2', 'ValueA5'),
('subject3', 'ValueA6'),
('subject3', 'ValueA7');

INSERT INTO Table2
(`subject`, `value`)
VALUES
('subject1', 'ValueB1'),
('subject1', 'ValueB2'),
('subject2', 'ValueB3'),
('subject1', 'ValueB4'),
('subject2', 'ValueB5'),
('subject3', 'ValueB6');

INSERT INTO Table3
(`subject`, `value`)
VALUES
('subject1', 'ValueC1'),
('subject2', 'ValueC2'),
('subject2', 'ValueC3'),
('subject2', 'ValueC4'),
('subject2', 'ValueC5'),
('subject3', 'ValueC6');

You need to use NOT EXISTS along with the UNION ALL . 您需要将NOT EXISTSUNION ALL一起使用。

I think it's bit complicated with three tables, but here: 我认为三个表有点复杂,但是在这里:

select *
from (
    select coalesce(t.subject, t3.subject) subject,
        t.value1,
        t.value2,
        t3.value value3
    from (
        select coalesce(t1.subject, t2.subject) subject,
            t1.value value1,
            t2.value value2
        from Table1 as t1
        left join Table2 as t2 on RIGHT(t2.value, 1) = RIGHT(t1.value, 1)
            and t1.subject = t2.subject

        union all

        select coalesce(t1.subject, t2.subject),
            t1.value,
            t2.value
        from Table1 as t1
        right join Table2 as t2 on RIGHT(t2.value, 1) = RIGHT(t1.value, 1)
            and t1.subject = t2.subject
        where not exists (
                select 1
                from table1 t
                where t.subject = t2.subject
                    and right(t.value, 1) = right(t2.value, 1)
                )
        ) t
    right join table3 t3 on t.subject = t3.subject
        and right(coalesce(t.value1, t.value2), 1) = right(t3.value, 1)

    union all

    select coalesce(t.subject, t3.subject) subject,
        t.value1,
        t.value2,
        t3.value value3
    from (
        select coalesce(t1.subject, t2.subject) subject,
            t1.value value1,
            t2.value value2
        from Table1 as t1
        left join Table2 as t2 on RIGHT(t2.value, 1) = RIGHT(t1.value, 1)
            and t1.subject = t2.subject

        union all

        select coalesce(t1.subject, t2.subject),
            t1.value,
            t2.value
        from Table1 as t1
        right join Table2 as t2 on RIGHT(t2.value, 1) = RIGHT(t1.value, 1)
            and t1.subject = t2.subject
        where not exists (
                select 1
                from table1 t
                where t.subject = t2.subject
                    and right(t.value, 1) = right(t2.value, 1)
                )
        ) t
    left join table3 t3 on t.subject = t3.subject
        and right(coalesce(t.value1, t.value2), 1) = right(t3.value, 1)
    where not exists (
            select 1
            from table3 t2
            where t2.subject = t.subject
                and right(t2.value, 1) = right(coalesce(t.value1, t.value2), 1)
            )
    ) t
order by subject,
    value1,
    value2,
    value3;

Demo 演示版

I think the best way to emulate a full join in MySQL is to select all the key values first and then use left join . 我认为在MySQL中模拟full join联接的最佳方法是先选择所有键值,然后使用left join However, you are not looking for a full join . 但是,您不是在寻找full join That would produce a Cartesian product for each subject. 这将为每个主题产生笛卡尔积。

You want to "list" each subject independently in each column. 您要在每个列中独立地“列出”每个主题。 For that, you can use union all , group by , and variables: 为此,您可以使用union allgroup by和变量:

select subject,
       max(value1) as value1,
       max(value2) as value2,
       max(value3) as value3
from ((select t1.subject, t1.value as value1, NULL as value2, NULL as value3
              (@rn1 := if(@s1 = subject, @rn1 + 1,
                          if(@s1 := subject, 1, 1)
                         )
              ) as rn
       from table1 t1 cross join
            (select @rn1 := 0, @s1 := '') params
      ) union all
      (select t2.subject, NULL, t2.value, NULL as value3
              (@rn2 := if(@s2 = subject, @rn2 + 1,
                          if(@s2 := subject, 1, 1)
                         )
              ) as rn
       from table2 t2 cross join
            (select @rn2 := 0, @s2 := '') params
      ) union all
      (select t3.subject, NULL as value1, NULL as value2, t3.value as value3
              (@rn3 := if(@s3 = subject, @rn3 + 1,
                          if(@s3 := subject, 1, 1)
                         )
              ) as rn
       from table3 t3 cross join
            (select @rn3 := 0, @s3 := '') params
      )
     )
group by subject, rn;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM