简体   繁体   English

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

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

I'm attempting to combine multiple rows into individual rows with multiple columns, where the data is from three tables. 我正在尝试将多行合并为具有多列的单个行,其中数据来自三个表。 I followed the suggestions in MySQL pivot table but the question and answers do not account for multiple joins. 我遵循了MySQL数据透视表中的建议,但问题和答案并未考虑多个联接。

Here are the underlying tables: 以下是基础表:

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

Here are the expected results: 这是预期的结果:

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

I can get pretty close to the results I want with: 我可以很接近我想要的结果:

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

but as expected, this yields the codes only: 但是正如预期的那样,这仅产生以下代码:

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

and I'm interested in replacing the codes with the longer descriptions from table c. 并且我有兴趣用表c中的较长描述替换代码。

The first step is to use case to return multiple columns of data from multiple rows within the same table using the technique from pivot tables in mysql : 第一步是使用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 

This yields the correct results for type8 but nulls for type9: 这将为type8产生正确的结果,但对于type9为空:

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

The next step is to get the results for type9: 下一步是获取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

This yields: 这样产生:

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

If these two results are unioned together with 如果将这两个结果与

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

the rows still need to be combined: 这些行仍然需要合并:

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

Finally, I was able to achieve the expected results by using the aggregating technique for removing nulls from a unioned query : 最后,通过使用聚合技术从联合查询中删除空值 ,我能够达到预期的结果:

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

which yields the results as expected: 得到预期的结果:

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

Another way to get the desired results is to create a pseudo union by combining ifnull(.,.) with 2 left join statements and then aggregating the cid 's to mimic a pivot . 获得期望结果的另一种方法是通过将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