【问题标题】:MySQL simple localizationMySQL简单本地化
【发布时间】:2015-05-06 16:52:45
【问题描述】:

我正在尝试在我的数据库中进行某种本地化。

例如,我有 3 张桌子(img 1)。语言表包含不同的语言。本地化表有 3 个字段:“id” - 字符串的 id,“语言” - 字符串的语言(id 和语言是我的主键),“值” - 本地化的字符串。 tableOne 有 'id'、'Col1' 和 'Col2' - 这些字段包含可本地化字符串的 ID。

所以在本地化之后,我希望得到一张绿色表格而不是原始表格(取决于语言参数)。

我已经这样做了,并且可以正常工作,但是我想知道是否有其他更好的方法可以做到这一点,因为现在我必须为每个列创建 INNER JOIN 块,该块必须本地化。我只是害怕它会非常非常慢。 我试图创建一个临时表来选择所需语言的所有记录,然后我也在做同样的事情。内连接,但只能在一种语言的记录中执行搜索。但它不起作用,因为我仍然必须对该临时表使用多个内部联接,这是不可能的。

SELECT 
    `One`.`id` AS 'id',
    `loc1`.`value` AS 'Col1',
    `loc2`.`value` AS 'Col2'
FROM
    `tableOne` AS `One`
        INNER JOIN
            `localization` AS `loc1` 
        ON `loc1`.`id` = `One.Col1`
        AND `loc1`.`language` = 'en'
        
        INNER JOIN
            `localization` AS `loc2` 
        ON `loc2`.`id` = `One.Col2`
        AND `loc2`.`language` = 'en'

图片1

【问题讨论】:

  • 我觉得这个问题非常广泛,也可以基于意见(因为人们可能对如何处理这个问题有不同的看法)。你有具体的问题吗?你说你有什么工作,所以我不确定你在问什么。
  • @McAdam331,我想避免多个内连接至少能够使用这个解决方案(内连接,但只能在一种语言的记录中执行搜索。但它不起作用因为我仍然必须对该临时表使用多个内部连接,这是不可能的。)。或者也许还有其他方法可以通过匹配表“本地化”中的值来替换“tableOne”的值
  • 不知道你每张表有多少条记录。如果它们是一个相对较小的数字,您最好找到一种将它们保存在内存中的方法,而不是每次都查询。
  • 它应该是整个网站的全球本地化系统。将至少有 5 种语言和至少 1000 个值(开始时)进行本地化(小事和大文本)。所以它不是一个解决方案
  • 是的,您需要加入需要本地化的每一列。将languages.id(和localization.language)更改为INT,您很可能会看到更好的性能......如果您需要这2个字符语言代码,请将它们作为语言表中的单独字段保存。

标签: mysql


【解决方案1】:

如果您想减少所需的JOINS 数量,请尝试按行而不是按列显示值。你可以这样做:

SET @lang := 'en';

SELECT 1, tmp.value
FROM(
  SELECT value
  FROM localization
  WHERE language = @lang AND id IN(543, 345)) tmp;

我首先设置一个语言参数,然后使用 IN 运算符中的 id 从本地化表中提取该语言的所有值。你会得到这样的结果:

| 1 | one |
| 1 | two |

如果您必须使用第一个表中给出的格式,请尝试执行一个内部连接,您可以在其中提取特定语言和 ID,如下所示:

SELECT t1.id, t1.col1, t1.col2, 
  CASE WHEN l.id = t1.col1 THEN l.value ELSE null END AS col1Value,
  CASE WHEN l.id = t1.col2 THEN l.value ELSE null END AS col2Value
FROM firstTable t1
JOIN localization l ON l.id IN (t1.col1, t1.col2) AND l.language = @lang;

不幸的是,这不会为您提供最终解决方案,它会为您提供如下值:

| 1 | 543 | 345 | one  | null |
| 1 | 543 | 345 | null | two  |

要将它们包装成一列并删除空值,只需添加MAX()

这将为您拥有的每一列运行一个 case 语句,但它只有一个 JOIN 并且看起来更易于管理:

SELECT t1.id,
  MAX(CASE WHEN l.id = t1.col1 THEN l.value ELSE null END) AS col1Value,
  MAX(CASE WHEN l.id = t1.col2 THEN l.value ELSE null END) AS col2Value
FROM firstTable t1
JOIN localization l ON l.id IN (t1.col1, t1.col2) AND l.language = @lang
GROUP BY t1.id;

这是一个SQL Fiddle 示例。我认为案例块不会让您陷入太多困境,但请让我知道这对您的实际数据库有何影响。

【讨论】:

  • 是的,这很好,但我添加了 GROUP BY t1.id bcuz 有多个值的结果不正确。谢谢你在我身上浪费时间。真的有帮助。很多
  • @FiftyStars 你是对的,很抱歉我忘记了。在我的示例中,我只使用了一个 id,所以我没有意识到这是一个问题。我将编辑答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-18
  • 2010-10-23
  • 1970-01-01
  • 2012-02-24
  • 2019-04-11
  • 1970-01-01
相关资源
最近更新 更多