繁体   English   中英

如何将多行与来自MySQL中多个表的多个联接合并

[英]How to combine multiple rows with multiple joins from multiple tables in mysql

我正在尝试将多行合并为具有多列的单个行,其中数据来自三个表。 我遵循了MySQL数据透视表中的建议,但问题和答案并未考虑多个联接。

以下是基础表:

table n
+------+----+------+
| name | id | code |
+------+----+------+
| foo  |  1 | NULL |
| bar  |  2 | z    |
| baz  |  3 | y    |
+------+----+------+

table ac
+------+----+
| code | id |
+------+----+
| h    |  1 |
| i    |  2 |
+------+----+

table c
+-----+------+-------+
| cid | code | desc  |
+-----+------+-------+
|   9 | h    | desch |
|   9 | i    | desci |
|   8 | z    | descz |
|   8 | y    | descy |
+-----+------+-------+

这是预期的结果:

+------+-------+-------+
| name | type8 | type9 |
+------+-------+-------+
| foo  | null  | desch |
| bar  | descz | desci |
| baz  | descy | null  |
+------+-------+-------+

我可以很接近我想要的结果:

select 
n.name,
n.code as type8,
ac.code as type9
from n
left join ac
on ac.id=n.id

但是正如预期的那样,这仅产生以下代码:

+------+-------+-------+
| name | type8 | type9 |
+------+-------+-------+
| foo  | null  | h     |
| bar  | z     | i     |
| baz  | y     | null  |
+------+-------+-------+

并且我有兴趣用表c中的较长描述替换代码。

第一步是使用case ,使用mysql中数据透视表中的技术从同一表中的多行返回多列数据:

select
n.name,
case when c.cid=8 then c.desc end as type8,
case when c.cid=9 then c.desc end as type9
from n
left join c  
on n.code=c.code 

这将为type8产生正确的结果,但对于type9为空:

+------+-------+-------+
| name | type8 | type9 |
+------+-------+-------+
| foo  | null  | null  |
| bar  | descz | null  |
| baz  | descy | null  |
+------+-------+-------+

下一步是获取type9的结果:

select
n.name,
case when c.cid=8 then c.desc end as type8,
case when c.cid=9 then c.desc end as type9
from n
left join ac
on ac.id=n.id
left join c
on c.code=ac.code

这样产生:

+------+-------+-------+
| name | type8 | type9 |
+------+-------+-------+
| foo  | null  | desch |
| bar  | null  | desci |
| baz  | null  | null  |
+------+-------+-------+

如果将这两个结果与

select 
n.name,
case when c.cid=8 then c.desc end as type8,
case when c.cid=9 then c.desc end as type9
from n
left join c  
on n.code=c.code

union

select
n.name,
case when c.cid=8 then c.desc end as type8,
case when c.cid=9 then c.desc end as type9
from n
left join ac
on ac.id=n.id
left join c
on c.code=ac.code

这些行仍然需要合并:

+------+-------+-------+
| name | type8 | type9 |
+------+-------+-------+
| bar  | descz | null  |
| baz  | descy | null  |
| foo  | null  | null  |
| foo  | null  | desch |
| bar  | null  | desci |
| baz  | null  | null  |
+------+-------+-------+

最后,通过使用聚合技术从联合查询中删除空值 ,我能够达到预期的结果:

select 
n.name,
min(type8), min(type9)
from
(select 
n.name,
case when c.cid=8 then c.desc end as type8,
case when c.cid=9 then c.desc end as type9
from n
left join c  
on n.code=c.code

union
select
n.name,
case when c.cid=8 then c.desc end as type8,
case when c.cid=9 then c.desc end as type9
from n
left join ac
on ac.id=n.id
left join c
on c.code=ac.code) as n
group by n.name

得到预期的结果:

+------+-------+-------+
| name | type8 | type9 |
+------+-------+-------+
| foo  | null  | desch |
| bar  | descz | desci |
| baz  | descy | null  |
+------+-------+-------+

获得期望结果的另一种方法是通过将ifnull(.,.)与2个left join语句组合在一起,然后聚合cid来模拟一个pivot ifnull(.,.)从而创建伪联合。

select name
    , min(if(cid = 8, `desc`, null)) Type8
    , min(if(cid = 9, `desc`, null)) Type9
from (
    select cid, code, `desc`, ifnull(name1, name2) name from (
        select c.cid, c.code, c.desc, n1.name name1, n2.name name2
        from c
        left join n n1 on n1.code = c.code
        left join ac on ac.code = c.code
        left join n n2 on n2.id = ac.id
    ) q1
) p1
group by name
order by name
;

暂无
暂无

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

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