左连接与完全外连接相结合

时间:2016-08-12 17:49:46

标签: sql postgresql left-join full-outer-join

有一个主表,它引用了另外两个表。这两个表可能每个引用有多个条目。

主:

true

短:

private final String[] colors = new String[] { 
    "-fx-background-color:#49CC49;",
    "-fx-background-color:#5FCC49;",
    "-fx-background-color:#8ACC49;", 
    "-fx-background-color:#A0CC49;", 
    "-fx-background-color:#CCCC49;", 
    "-fx-background-color:#CCB649;", 
    "-fx-background-color:#CC8A49;", 
    "-fx-background-color:#CC7449;", 
    "-fx-background-color:#CC4949;" };

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

我的第一次尝试是(sqlfiddle

(id, lang)

会让出太多条目。

下一个是(sqlfiddle

| 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

给出了期望的结果,但对我来说这对于如此简单的(?)要求似乎过分了。

所以这是我的问题,是否有更简单的方法?

2 个答案:

答案 0 :(得分:1)

IMO您在数据模式中遗漏的是可用语言的字典。如果介绍它,其他所有变得更简单。

所需的字典冷却:

  • array['en','de','fr']
  • 这样的简单常量
  • 真正的表
  • short_desclong_desc
  • 等表中收集语言代码的视图

由您决定哪种情况更适合您的目的。

在下面的示例中,我们将语言字典视为CTE:

with lang(code) as (values('en'),('de'),('fr'))
select m.*, lang.code
from main m cross join lang;

╔════╤═══════╤═════╤═════╤══════╗
║ id │ mname │ sid │ lid │ code ║
╠════╪═══════╪═════╪═════╪══════╣
║  1 │ a1    │   1 │   2 │ en   ║
║  2 │ a2    │   2 │   3 │ en   ║
║  3 │ a3    │   1 │   1 │ en   ║
║  1 │ a1    │   1 │   2 │ de   ║
║  2 │ a2    │   2 │   3 │ de   ║
║  3 │ a3    │   1 │   1 │ de   ║
║  1 │ a1    │   1 │   2 │ fr   ║
║  2 │ a2    │   2 │   3 │ fr   ║
║  3 │ a3    │   1 │   1 │ fr   ║
╚════╧═══════╧═════╧═════╧══════╝
(9 rows)

如您所见,现在我们为每种语言设置了单独的行,接下来的最后一步是使用idlang字段将其他两个表连接到上面的查询:

with lang(code) as (values('en'),('de'),('fr'))
select m.*, lang.code, s.sdesc, l.ldesc
from main m cross join lang
  left join short_desc s on s.id = m.sid and s.lang = lang.code
  left join long_desc l on l.id = m.lid and l.lang = lang.code;

╔════╤═══════╤═════╤═════╤══════╤═══════╤═══════╗
║ id │ mname │ sid │ lid │ code │ sdesc │ ldesc ║
╠════╪═══════╪═════╪═════╪══════╪═══════╪═══════╣
║  3 │ a3    │   1 │   1 │ de   │ S1    │ L1    ║
║  3 │ a3    │   1 │   1 │ en   │ S2    │ L2    ║
║  3 │ a3    │   1 │   1 │ fr   │ ░░░░  │ ░░░░  ║
║  1 │ a1    │   1 │   2 │ de   │ S1    │ L3    ║
║  1 │ a1    │   1 │   2 │ en   │ S2    │ ░░░░  ║
║  1 │ a1    │   1 │   2 │ fr   │ ░░░░  │ ░░░░  ║
║  2 │ a2    │   2 │   3 │ de   │ S3    │ ░░░░  ║
║  2 │ a2    │   2 │   3 │ en   │ ░░░░  │ L4    ║
║  2 │ a2    │   2 │   3 │ fr   │ ░░░░  │ ░░░░  ║
╚════╧═══════╧═════╧═════╧══════╧═══════╧═══════╝

答案 1 :(得分:0)

您希望> git add . > git commit -m "my commit" > git push 条件left join lang子句中的条件:

on

这应该是Goldilock的解决方案,只有正确的行数。

甚至:

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 and s.lang = l.lang;