在表(tbl_i18n)中记录不同语言的文本,其结构如下:
text_FK | language_FK | value
-----------------------------
1 | 1 | hello
1 | 2 | hallo
2 | 1 | world
3 | 1 | test
通过简单的连接给出特定语言(id = 2)的文本:
SELECT [value] FROM tbl_i18n i
JOIN tbl_products p ON p.text_id = i.text_FK
JOIN tbl_languages l ON l.id = i.language_FK AND i.language FK = 2;
结果是:
value
-------
hallo
如何更改上述 select 语句,以便我们可以获得默认语言,并且当文本字段的翻译不存在时,将显示其后备文本,结果将变为:
value
-------
hallo
world
test
LEFT JOIN
语言表两次。第一次用于所需语言,第二次用于后备值。使用 COALESCE
选择所需语言(如果可用),否则选择后备语言。
SELECT coalesce(l1.[value], l2.[value])
FROM tbl_i18n i
JOIN tbl_products p ON p.text_id = i.text_FK
LEFT JOIN tbl_languages l1 ON l.id = i.language_FK AND i.language_FK = 2
LEFT JOIN tbl_languages l2 ON l.id = i.language_FK AND i.language_FK = 1;
我想用简单的英语来说,你想要每个
language_FK
的最高可用text_FK
。
WITH X AS (
SELECT *
,ROW_NUMBER() OVER (PARTITION BY text_FK ORDER BY language_FK DESC)rn
FROM TableName
)
SELECT *
FROM X
WHERE X.rn = 1
让我们举一个更难的例子: 我有一个 post_translations 表,其中包含每个语言环境的帖子的所有翻译,语言环境是一个字符串,post_id 是帖子的 id。
我们想要选择所有“it”帖子并回退到“en”。
SELECT * FROM
(
SELECT post_translations.* ,ROW_NUMBER() OVER (PARTITION BY post_id ORDER BY (CASE locale WHEN 'it' then 1 WHEN 'en' THEN 2 ELSE 3 END)) AS tr_rank
FROM post_translations
) ranked_post_translations
WHERE tr_rank=1
我们将从子查询中选择所有帖子,该子查询将以升序排列我们的翻译(1 是首选翻译);我们将在按首选翻译排序的分区上使用 ROW_NUMBER 来计算“翻译排名”(我们将使用 CASE,因为我们无法按语言环境字符串排序)。
只需将多种后备语言添加到 CASE 语句中即可轻松扩展该脚本(例如 it=1、en=2、de=3、es=4 等)