MySQL加入和null

时间:2014-01-16 19:51:15

标签: mysql database database-design left-join

我已经对互联网进行了几个小时的巡航,似乎无法想象这一个!

我有一些表格:

ResourceShort

idResourceShort idLanguage
1 播放 1
2 易于 1
... ...
257 JOUER 2

ResourceOriginal

idResourceOriginal 上下文
1 播放 按钮来玩游戏
2 轻松 ai模式
... ... ...
257 游戏 NULL

ResourceOriginal_ResourceShort

idResourceOriginal idResourceShort
1 1
1 257
... ...
2 2

语言

idLanguage 名称
1 英语
2
3 意大利
... ...

我希望检索每种语言的所有值,如下所示:

翻译

语言名称 context value
英语 按钮来玩游戏 播放
法语 玩游戏 Jouer
意大利 按钮来玩游戏 NULL

我目前有这样的查询:

  

SELECT Language.name,ResourceOriginal.context,ResourceShort.value   来自ResourceShort   JOIN ResourceOriginal_ResourceShort ON ResourceOriginal_ResourceShort.idResourceShort = ResourceShort.idResourceShort   JOIN ResourceOriginal ON ResourceOriginal_ResourceShort.idResourceOriginal = ResourceOriginal.idResourceOriginal   JOIN Language ON Language.idLanguage = ResourceShort.idLanguage   在哪里ResourceOriginal.value喜欢'播放

...它只会产生英语和法语的结果 - 我也希望包含空值。

注意:在ResourceShort中,意大利语不存在该行 - 该翻译尚不存在。

基本上,我想在数据库中列出某个单词的所有翻译。

如果不清楚:

  • ResourceOriginal是原始字符串

  • ResourceShort是原始字符串的翻译,包括原始语言。 (是的,数据是多余的,但不太复杂的查询)。

非常感谢任何帮助,解决方案将得到我的投票!

谢谢你们!

3 个答案:

答案 0 :(得分:1)

使用OR ro.value IS NULLRIGHT JOIN Language尝试获取所有语言

SELECT 
  l.name,
  ro.context,
  rs.value 
FROM
  ResourceShort rs 
  RIGHT JOIN `Language` l 
    ON l.idLanguage = rs.idLanguage 
  LEFT JOIN ResourceOriginal_ResourceShort rors 
    ON rors.idResourceShort = rs.idResourceShort 
  LEFT JOIN ResourceOriginal ro 
    ON rors.idResourceOriginal = ro.idResourceOriginal 
WHERE ro.value LIKE 'Play%' 
  OR ro.value IS NULL 

See Fiddle Demo

答案 1 :(得分:1)

对ResourceOriginal使用LEFT OUTER JOIN。

答案 2 :(得分:1)

我想我理解你想要归还的东西;下面的查询可以帮到你。

您希望获得ResourceOriginal表中与某个谓词匹配的所有行(在您的示例中为value 'Play'

然后,对于Language中的每一行(如果您有英语,法语和意大利语),您希望查找相应的值。我们在查询中使用的“技巧”是CROSS JOIN。这让我们成为每种语言的匹配行。所以,如果我们从ResourceOriginal返回一行,并且我们从Language获得三行,我们将返回三行。

使用该集合,我们可以查找实际值。但是我们需要使这些查找成为OUTER连接,这样我们就不会消除任何行。我们希望保留为每种语言生成的行,即使我们找不到匹配项也是如此。当没有找到匹配的行时,我们只返回NULL。

这样的事情:

SELECT l.name
     , o.context
     , s.value
  FROM Language l 
 CROSS 
  JOIN ResourceOriginal o
  LEFT
  JOIN ResourceOriginal_ResourceShort r
    ON r.idResourceOriginal = o.idResourceOriginal
  LEFT
  JOIN ResourceShort s
    ON s.idResourceShort = r.idResourceShort
   AND s.idLanguage = l.idLanguage
 WHERE o.value LIKE 'Play'

注意:因为这是在进行OUTER连接以保留空值,并且因为RO_RS中有多行与RO中的行相关,所以我们会得到多行。

如果数据模型略有不同,可以避免这种情况。如果RO_RS表包含idLanguage值(因此可以在JOIN子句中包含适当的谓词)。或者,如果完全消除了RO_RS表,则RS表可以具有RO表的直接外键。

我们可以使用GROUP BY和MAX聚合值...但是这不能正确处理模型允许的更一般情况......也就是说,对于RS中的两行或更多行相同的语言,与同一个RO相关。 (该RO_RS表允许多对多,)

请注意,对于任何给定的RS,数据模型允许使用相同语言的两个(或更多)RO

考虑是否还添加了这些行:

RS
  258, 'bazinga', 3
  259, 'booyah' , 3

RO_RS
  1, 258
  1, 259

这会导致将这些行添加到结果集中。

language   context    value
--------   -------    -------
Italian    button...  bazinga  
Italian    button...  booyah