MySQL多表SELECT

时间:2014-02-06 21:49:18

标签: mysql sql select subquery multiple-tables

我在组合MySQL查询时遇到了一些问题。它是多语言,多目标站点的一部分,因此我需要从多个表中检索站点的一些文本部分,并使用回退。可能命中的顺序:

  

更正@ local_tbl> english @ local_tbl>更正@ global_tbl>   英语@ global_tbl。

因为它会被高度使用,所以我希望保持快速且连接数少,但只返回1行。我尝试了以下几种方法,但我确信有更好的解决方案。


FROM子句中的子查询:如果任何子查询给出0行,它就会死掉。即使它有效,也需要一些PHP解释:

SELECT * FROM

(SELECT `sp_content` AS sp_local FROM `loc-ae_siteparts` WHERE `sp_name` = 'name_of_some_sitepart' AND `sp_lang` = 'de' AND `sp_corrected`='1' LIMIT 1) as local,
(SELECT `sp_content` AS sp_local_en FROM `loc-ae_siteparts` WHERE `sp_name` = 'name_of_some_sitepart' AND `sp_lang` = 'en' LIMIT 1) as local_en,
(SELECT `sp_content` AS sp_global, `sp_corrected` as sp_global_corrected FROM `loc-global_siteparts` WHERE `sp_name` = 'name_of_some_sitepart' AND `sp_lang` = 'de' LIMIT 1) as global,
(SELECT `sp_content` AS sp_global_en FROM `loc-global_siteparts` WHERE `sp_name` = 'name_of_some_sitepart' AND `sp_lang` = 'en' LIMIT 1) as global_en

TEMP表:这里我关注性能,不能使用内存引擎,因为它涉及文本字段。小鸟的核武器?

CREATE TEMPORARY TABLE IF NOT EXISTS `random_tbl_name` AS (SELECT `sp_content` FROM `loc-global_siteparts` LIMIT 0);

INSERT INTO `random_tbl_name` SELECT `sp_content` FROM `loc-ae_siteparts` WHERE `sp_name` = 'name_of_some_sitepart' AND `sp_lang` = 'de' AND `sp_corrected` = '1' LIMIT 1;
INSERT INTO `random_tbl_name` SELECT `sp_content` FROM `loc-ae_siteparts` WHERE `sp_name` = 'name_of_some_sitepart' AND `sp_lang` = 'en' LIMIT 1;
INSERT INTO `random_tbl_name` SELECT `sp_content` FROM `loc-global_siteparts` WHERE `sp_name` = 'name_of_some_sitepart' AND `sp_lang` = 'de' AND `sp_corrected` = '1' LIMIT 1;
INSERT INTO `random_tbl_name` SELECT `sp_content` FROM `loc-global_siteparts` WHERE `sp_name` = 'name_of_some_sitepart' AND `sp_lang` = 'en' LIMIT 1;

SELECT * FROM `random_tbl_name` LIMIT 1;

编辑:感谢所有答案,他们真的很有帮助。

3 个答案:

答案 0 :(得分:1)

SELECT * FROM
    ((SELECT 1 precedence, `sp_content`
     FROM `loc-ae_siteparts` 
     WHERE `sp_name` = 'name_of_some_sitepart' AND `sp_lang` = 'de' AND `sp_corrected`='1'
     LIMIT 1)
     UNION
     (SELECT 2 precedence, `sp_content` 
     FROM `loc-ae_siteparts` 
     WHERE `sp_name` = 'name_of_some_sitepart' AND `sp_lang` = 'en' 
     LIMIT 1)
     UNION
     ...
    ) x
ORDER BY precedence
LIMIT 1

答案 1 :(得分:0)

当其中一个子查询为空时没有结果的原因是

select * from
s1, s2, s3, s4

你有一个隐含的联接。当其中一个子结果为空时,结果连接也是空的。

要解决此问题,您可以将子查询用作列。这将给出相同的结果,但是使用NULL值,其中subselect不返回任何行

SELECT (SELECT `sp_content` AS sp_local FROM `loc-ae_siteparts` WHERE `sp_name` = 'name_of_some_sitepart' AND `sp_lang` = 'de' AND `sp_corrected`='1' LIMIT 1) as local,
       (SELECT `sp_content` AS sp_local_en FROM `loc-ae_siteparts` WHERE `sp_name` = 'name_of_some_sitepart' AND `sp_lang` = 'en' LIMIT 1) as local_en,
       (SELECT `sp_content` AS sp_global, `sp_corrected` as sp_global_corrected FROM `loc-global_siteparts` WHERE `sp_name` = 'name_of_some_sitepart' AND `sp_lang` = 'de' LIMIT 1) as global,
       (SELECT `sp_content` AS sp_global_en FROM `loc-global_siteparts` WHERE `sp_name` = 'name_of_some_sitepart' AND `sp_lang` = 'en' LIMIT 1) as global_en

答案 2 :(得分:0)

我过去做过类似的事情:

SELECT COALESCE(ls1.sp_content, ls2.sp_content) AS sp_content
FROM (SELECT 1) a
LEFT JOIN loc-ae_siteparts ls1
  ON ls1.sp_name = 'name_of_some_sitepart' AND ls1.sp_lang = 'de' AND ls1.sp_corrected = '1'
LEFT JOIN loc-ae_siteparts ls2
  ON ls2.sp_name = 'name_of_some_sitepart' and ls2.sp_lang = 'en'
LIMIT 1