2014-02-06 103 views
0

我被一個結合MySQL查詢卡住了一點。它是多語言,多目標站點的一部分,因此我需要從多個表中檢索站點的一些文本部分,並使用備用。可能命中的順序:MySQL多表選擇

糾正@ local_tbl>英語@ 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; 

編輯:感謝所有的答案,他們是真正的幫助。

回答

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

這是一個很好的一個 – Leo

+0

謝謝,像魅力一樣工作。速度和知識一方面。 ;) – gramgram

0

你沒有結果時,子查詢的一個是空的原因是,與

select * from 
s1, s2, s3, s4 

你有一個隱含的加入。當其中一個子結果爲空時,生成的連接也是空的。

要解決這個問題,可以使用子查詢作爲列。這會給你同樣的結果,但與NULL值,其中子查詢不返回行

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

謝謝,清除子查詢部分! – gramgram

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