2016-11-11 53 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