示例:
> SELECT name, culture FROM city_i18n WHERE ID = 2745;
+-------+---------+
| name | culture |
+-------+---------+
| Paris | en_GB |
| París | es_ES |
| Paris | pt_BR |
| Paris | pt_PT |
+-------+---------+
4 rows in set (0.00 sec)
> SELECT DISTINCT name FROM city_i18n WHERE ID = 2745 AND culture IN ('es_ES', 'en_GB');
+-------+
| name |
+-------+
| Paris |
+-------+
1 row in set (0.00 sec)
> SELECT DISTINCT name FROM city_i18n WHERE ID = 2745 AND culture IN ('es_ES', 'pt_PT');
+-------+
| name |
+-------+
| París |
+-------+
1 row in set (0.00 sec)
注意两个SELECT DISTINCT
的不同输出:Paris,París(带重音)
现在,始终给予es_ES
优先权的简单方法是什么(即始终获得带重音的París)?
由于存在一些问题,一些澄清:只有口音不同的城市名称(根据整理)应该只显示一次。在这种情况下,显示的名称应具有文化es_ES
的重音符。
答案 0 :(得分:3)
问题是您的数据库中使用的归类序列。根据您的RDBMS,有大量关于校准序列的信息。更改归类序列时需要非常小心,因为它会产生意想不到的后果。
归类序列用于测试列的相等性或不等式。根据使用的排序规则,以下语句可以全部评估为真或假:
'TexT' = 'text'
'TEXT' = 'text'
'áéíóú' = 'aeiou'
在您的情况下,您需要选择一个将重音字母和常规字母视为不同值的整理顺序。目前您的数据库正在确定它们是相同的。完成后,您可以根据自己喜欢的culture
只是添加它似乎您的数据库当前正在确定Paris = París
并且我怀疑无法保证将选择哪个不同的值,类似于没有确定结果集的顺序这一事实除非使用ORDER BY子句。
我想了一会儿。我认为最好的办法是创建一个CultureRank
CREATE TABLE CultureRank
(
Rank INTEGER,
Culture VARCHAR(5)
);
INSERT INTO CultureRank VALUES (1, 'es_ES');
INSERT INTO CultureRank VALUES (2, 'en_GB');
INSERT INTO CultureRank VALUES (3, 'pt_BR');
INSERT INTO CultureRank VALUES (4, 'pt_PT');
SELECT
Name
FROM
City_i18n
LEFT JOIN CultureRank ON City_i18n.Culture = CultureRank.Culture
WHERE
ID = 2745
AND City_i18n.Culture IN ('es_ES', 'pt_PT') -- If Required
ORDER BY
IF(ISNULL(CultureRank.Culture),1,0),
CultureRank.Rank
LIMIT 1;
如果city_i18n中的文化不在CultureRank中,则需要ORDER BY ISNULL。这里的IsNull函数将确保CultureRank表中的文化被赋予最高优先权,然后如果这些文化都没有与城市相关联,那么引擎将从city_i18n表中为该城市选择随机文化。如果您希望将不在CultureRank中的文化作为首要任务,那么请更换1& ISNULL函数中的0个参数。
编辑:
SELECT
Name
FROM
City_i18n
LEFT JOIN CultureRank ON City_i18n.Culture = CultureRank.Culture
WHERE
ID = 2745
AND City_i18n.Culture IN ('es_ES', 'pt_PT') -- If Required
AND NOT EXISTS (
SELECT
NULL
FROM
City_i18n Cities
LEFT JOIN CultureRank CitiesRank ON Cities.Culture = CitiesRank.Culture
WHERE
City_i18n.Name = Cities.Name
AND CultureRank.Rank < CitiesRank.Rank)
这应该从City_i18n表中获取给定ID的每个Name,除非根据您的归类序列,在CultureRank表中具有更高排名的另一个具有相同名称的记录。
答案 1 :(得分:0)
PHP / MySQL中的Unicode很痛苦。请使用以下两行代码:
setlocale(LC_ALL, 'en_US.utf8');
mysql_query("SET NAMES 'utf8'");
将它们洒在你的代码中,如圣水。
答案 2 :(得分:0)
看起来我找到了解决方案:
SELECT name FROM city_i18n
WHERE (name != (SELECT name FROM city_i18n WHERE ID = 2745 AND culture = 'es_ES')
OR culture = 'es_ES')
AND ID = 2745 AND culture IN ('es_ES', 'en_GB');
如果有更好的解决方案,我很高兴听到它!