在MySQL子查询中选择多个列/字段

78

基本上,有一个属性表和翻译表 - 一个属性有多个翻译。

我需要从指定语言的每个属性的翻译中选择id和value,即使在该语言中没有翻译记录。我可能缺少一些连接技术或连接(不涉及语言表)在这里不起作用,因为以下内容不会返回具有不存在于指定语言中的翻译的属性。

select a.attribute, at.id, at.translation 
from attribute a left join attributeTranslation at on a.id=at.attribute
where al.language=1;

所以我正在使用像这样的子查询,问题在于使用相同参数对同一张表进行两个子查询(感觉会影响性能,除非MySQL将它们分组,但我怀疑这一点,因为它会让你执行许多类似的子查询)

select attribute, 
(select id from attributeTranslation where attribute=a.id and language=1),
(select translation from attributeTranslation where attribute=a.id and language=1), 
from attribute a;

我希望能够从一个查询中获取id和翻译,因此我将列连接起来,并稍后从字符串中获取id,这至少会生成单个子查询,但仍然不太对。

select attribute,
(select concat(id,';',title)
    from offerAttribute_language 
    where offerAttribute=a.id and _language=1
)
from offerAttribute a

所以问题来了。 有没有办法从单个子查询中获取多列,或者我应该使用两个子查询(MySQL足够聪明,可以将它们分组?)或者以下方式连接是正确的:

[[属性到语言]到翻译](连接3个表似乎比子查询性能更差)。

1个回答

130

是的,您可以这样做。您需要掌握的技巧是从表服务器中获取表格有两种方式的概念。一种方法是..

FROM TABLE A
另一种方法是什么?
FROM (SELECT col as name1, col2 as name2 FROM ...) B

注意到选择子句和括号组成了一个表,一个虚拟表。

因此,使用您的第二个代码示例(我猜测您希望检索哪些列):

SELECT a.attr, b.id, b.trans, b.lang
FROM attribute a
JOIN (
 SELECT at.id AS id, at.translation AS trans, at.language AS lang, a.attribute
 FROM attributeTranslation at
) b ON (a.id = b.attribute AND b.lang = 1)

请注意,在这个联接中,您的实际表格属性是第一个表格,而我称之为b的虚拟表格是第二个表格。

当虚拟表格是某种汇总表格时,这种技术非常有用。例如:

SELECT a.attr, b.id, b.trans, b.lang, c.langcount
FROM attribute a
JOIN (
 SELECT at.id AS id, at.translation AS trans, at.language AS lang, at.attribute
 FROM attributeTranslation at
) b ON (a.id = b.attribute AND b.lang = 1)
JOIN (
 SELECT count(*) AS langcount,  at.attribute
 FROM attributeTranslation at
 GROUP BY at.attribute
) c ON (a.id = c.attribute)

看起来怎么样?你已经生成了一个包含两列的虚拟表c,将其与另外两个表连接,使用其中一列作为ON子句,将另一列作为结果集中的一列返回。


SELECT a.attribute, b.id, b.translation FROM attribute a LEFT JOIN (SELECT id, translation, attribute FROM translation WHERE _language=1) b ON a.id=b.attribute 是我成功的代码,谢谢 :) - Martin
3
@Martin,你可以直接加入; 不需要虚拟表。SELECT a.a, tr.id, tr.translation FROM attribute a LEFT JOIN translation tr ON a.id=tr.attribute WHERE tr.language=1 - O. Jones
我之前提到过,可能没说清楚,有些记录没有翻译,所以如果我设置 language=1 但是没有翻译,我会错过属性记录。 - Martin
1
@O.Jones - 这个方法可以工作,但如果attributeTranslation表很大,那么它的效率可能比OP问题中使用的子查询要低得多,因为虚拟表不会从attribute_id索引中受益(假设有一个)。我很想知道是否有一种方法可以通过来自表a的列限制来实现构建虚拟表。到目前为止,我一直被困在OP的方法中。 - But those new buttons though..

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接