2016-11-11 49 views
0

我在MySQL中,InnoDB的使用SQL_CALC_FOUND_ROWS有一些問題UNION ALL。首先讓我展示一個簡單的數據庫模式來解釋這是怎麼回事...的MySQL,UNION ALL與SQL_CALC_FOUND_ROWS不工作有時

Database Schema

媒體表

media_id title 
------------------------------------- 
1   Empire of the Sun 

體裁類型表

genre_id name 
------------------------------------- 
1   Action 
2   Adventure 

區域設置表

locale_id code 
------------------------------------- 
1   en_US 
2   pt_BR 
3   fr_FR 

類型翻譯表

genre_id locale translation 
------------------------------------- 
1   1   Action 
1   2   Ação 
2   1   Adventure 
2   2   Aventura 

媒體流派表

media_id genre_id 
------------------------------------- 
1   1 
1   2 

現在很簡單:我需要返回與用戶區域兼容的流派名稱。假設用戶區域設置爲pt_BR。要我得到的結果我用瞭如下SQL:

select gt.name 
from media_genres mg 
inner join genre_translation gt on (mg.genre_id = gt.genre_id) 
where (mg.media_id = 1 and gt.locale_id = 2) 

它返回:

name 
------------------------------------- 
Ação 
Aventura 

但是,現在,讓我們假設用戶的語言環境是fr_FR。沒有fr_FR的翻譯,對吧?我找到的解決方案是使用UNION ALL與SQL_CALC_FOUND_ROWS,然後我用下面的SQL:

select SQL_CALC_FOUND_ROWS gt.name 
from media_genres mg 
inner join genre_translation gt on (mg.genre_id = gt.genre_id) 
where (mg.media_id = 1 and gt.locale_id = 3) 

UNION ALL 

select gt.name 
from media_genres mg 
inner join genre_translation gt on (mg.genre_id = gt.genre_id) 
where FOUND_ROWS() = 0 and (mg.media_id = 1 and gt.locale_id = 1) 

如果沒有找到行的LOCALE_ID = 3和media_id = 1,那麼我會得到的結果LOCALE_ID = 1(默認)和media_id = 1。

問題是:聲明有時會返回正確的數據,有時會返回沒有數據

而我的主要問題:爲什麼會發生這種情況?

+0

我不知道有第一'SELECT'首先執行的保證,所以你不能從第一取決於'FOUND_ROWS()'在第二個'SELECT'是行數一。 – Barmar

+0

您應該收到錯誤,因爲這兩個子查詢不會返回相同數量的列。第二個子查詢是否真的像第一個那樣返回'mg.genre_id,gt.name'? – Barmar

+0

感謝您的反饋!我寫錯了字段「mg.genre_id」,即使沒有這個字段在SQL中...我有相同的結果:有時數據被返回,有時不會... – itscaiqueck

回答

0

完成此操作的方法是使用LEFT JOIN加入轉換表,然後使用IFNULL在不匹配時提供默認值。

SELECT mg.genre_id, IFNULL(gt2.name, gt1.name) AS name 
FROM media_genres AS mg 
JOIN genre_translation AS gt1 ON mg.genre_id = gt.genre_id AND gt.locale_id = 1 
LEFT JOIN genre_translation AS gt2 ON mg.genre_id = gt.genre_id AND gt.locale_id = 3 
WHERE mg.media_id = 1 
+0

這工作得很好,我只是修復了「gt」。到「gt1」。和「gt2」。在加入聲明!非常感謝。這個查詢性能好嗎? – itscaiqueck

+0

只要你有'genre_translation.genre_id'上的索引就應該很好。 – Barmar