【发布时间】:2016-12-19 19:30:44
【问题描述】:
有一个主表,它引用了另外两个表。这两个表每个引用可能有多个条目。
主要:
| id | mname | sid | lid |
|----|-------|-----|-----|
| 1 | a1 | 1 | 2 |
| 2 | a2 | 2 | 3 |
| 3 | a3 | 1 | 1 |
短:
| id | lang | sdesc |
|----|------|-------|
| 1 | de | S1 |
| 1 | en | S2 |
| 2 | de | S3 |
| 3 | en | S4 |
(id, lang) 是唯一的。
长:
| id | lang | ldesc |
|----|------|-------|
| 1 | de | L1 |
| 1 | en | L2 |
| 2 | de | L3 |
| 3 | en | L4 |
(id, lang) 是唯一的。
我想将这三个表连接起来得到以下结果:
| mname | lang | sdesc | ldesc |
|-------|------|--------|--------|
| a1 | de | S1 | L3 |
| a1 | en | S2 | (null) |
| a2 | de | S3 | (null) |
| a2 | en | (null) | L4 |
| a3 | de | S1 | L1 |
| a3 | en | S2 | L2 |
我的第一次尝试是 (sqlfiddle)
select m.mname, s.lang, s.sdesc, l.lang, l.ldesc
from main m
left join short_desc s on s.id = m.sid
left join long_desc l on l.id = m.lid
这给了太多的条目。
下一个是 (sqlfiddle)
select m.mname, s.lang, s.sdesc, l.lang, l.ldesc
from main m
left join short_desc s on s.id = m.sid
left join long_desc l on l.id = m.lid
where s.lang = l.lang
这会遗漏有效的条目。
经过上述的许多变化和大量的玩弄,我想出了(sqlfiddle)
with x1 as (select m.id, m.mname, s.lang, s.sdesc
from main m
join short_desc s on s.id = m.sid),
x2 as (select m.id, m.mname, l.lang, l.ldesc
from main m
join long_desc l on l.id = m.lid)
select coalesce(x1.mname, x2.mname) mname,
coalesce(x1.lang, x2.lang) lang,
x1.sdesc,
x2.ldesc
from x1
full outer join x2 on x2.id = x1.id and x2.lang = x1.lang
这给出了预期的结果,但对我来说,这对于如此简单的 (?) 要求来说似乎太过分了。
所以这是我的问题,有没有更简单的方法?
【问题讨论】:
-
... from main m cross join (select * from unnest(array['de','en'])) lang(code) left join short_desc s on s.id = m.sid and lang.code = s.lang ... -
您的数据和想要的结果不匹配。您的结果要求 a2、en、null、L4 行,但您的数据针对 id 3 具有 L4。
-
@RelativePHPNewbie 是的,
m.lid = l.id,即m = (2, a2, 2, *3*)和l = (*3*, en, L4) -
@Abelisto 哇,想添加这个作为答案吗?我还不明白这个,但它似乎工作(sqlfiddle)
标签: sql postgresql left-join full-outer-join