[英]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.