从JOIN中选择2个条目为1行

时间:2014-01-24 16:23:59

标签: sql sql-server

我有3张桌子:

手册:

ManualId | Stuff...
---------+----------
180      | Stuff...

ManualLang:

ManualLangId | ManualId | LangId | Description
-------------+----------+--------+-----------------------
1            | 180      | FR-CA  | Description française
2            | 180      | EN-CA  | English description

郎:

LangId
---------
FR-CA
EN-CA

我正在使用语言表,以便轻松地为我的应用程序添加新语言。 manualLang表允许我的手动属性具有不同的语言,而不会重复我的手册,并避免在我的手册表中为不同的语言提供大量属性。此外,它将使我将来更容易以这种方式添加新语言,而无需修改所有表格来添加语言。

但我有一个问题。在我的MVC网站上,我需要使用它的语言来获取手册。所以为了做到这一点,我必须做一个选择查询,这将返回我:

Manual_Id | DescriptionFr         | DescriptionEn
----------------------------------|---------------------
180       | Description française | English description

到目前为止,我可以通过此查询获得结果

SELECT  m.ManualId,
            mlFr.Description as 'DescriptionFr',
            mlEn.Description as 'DescriptionEn'
FROM    Manual m
left join   ManualLang mlFr ON m.ManualId = mlFr.ManualId
left join   ManualLang mlEn ON m.ManualId = mlEn.ManualId
WHERE   m.ManualId = 180 AND mlFr.LangId = 'FR-CA' AND mlEn.LangId = 'EN-CA'

我的问题是......是否有可能以更清洁的方式做到这一点?

我应该使用一段时间吗? CTE?一个游标?或者这是我应该这样做的方式?我将不得不在我的应用程序中为许多其他查询复制它。

2 个答案:

答案 0 :(得分:2)

我认为这是一个明确的解决方案。您可以更改查询以将联接谓词移至join而不是where。就是这样。

select  m.ManualId
,       mlFr.Description as DescriptionFr
,       mlEn.Description as DescriptionEn
from    Manual m
left
outer
join    ManualLang mlFr
on      m.ManualId = mlFr.ManualId
and     mlFr.LangId = 'FR-CA'
left
outer
join    ManualLang mlEn
and     mlEn.LangId = 'EN-CA'
on      m.ManualId = mlEn.ManualId
where   m.ManualId = 180

答案 1 :(得分:1)

您可以使用单个联接和聚合来执行此操作:

SELECT  m.ManualId,
        max(case when ml.LangId = 'FR-CA' then ml.Description end) as DescriptionFr,
        max(case when ml.LangId = 'EN-CA' then ml.Description end) as DescriptionEn
FROM Manual m left join
     ManualLang ml
    ON m.ManualId = ml.ManualId
WHERE m.ManualId = 180 AND ml.LangId in ('FR-CA', 'EN-CA')
GROUP BY m.ManualId;

注意:您应该仅对字符串常量使用单引号,而不是列名。

编辑:

这个版本让你得到你需要的一切:

SELECT m.*,  ml.DescriptionFr, ml.DescriptionEn
FROM Manual m left join
     (select ml.ManualId,
             max(case when ml.LangId = 'FR-CA' then ml.Description end) as DescriptionFr,
             max(case when ml.LangId = 'EN-CA' then ml.Description end) as DescriptionEn
      from ManualLang ml
      where ml.ManualId = 180 and ml.LangId in ('FR-CA', 'EN-CA')
      group by ml.ManualId
     ) ml
     ON m.ManualId = ml.ManualId;