【问题标题】:Using subqueries for locale fallback in MySQL在 MySQL 中使用子查询进行语言环境回退
【发布时间】:2011-08-15 02:01:18
【问题描述】:

我有一个托管的在线商店产品,它支持各种数据类型的自定义字段。切入正题,任何人都可以通过添加到定义为的表来向任何记录添加额外的键/值对:

`storeId` varchar(20) NOT NULL,
`locale` varchar(100) NOT NULL,
`table` varchar(30) NOT NULL,
`id` varchar(50) NOT NULL,
`key` varchar(30) NOT NULL,
`value` mediumblob NOT NULL,
PRIMARY KEY (`storeId`, `locale`, `table`, `id`, `key`)

在欧洲,很多人都希望支持多种语言,因此每个键可以针对不同的区域设置多个值。每个商店都有一个默认区域(由店主指定)和一个活动区域(由客户选择)。

我试图放在一起的查询的行为如下:

  • storeIdtableid 以及活动区域设置和默认区域设置都是已知的。
  • 如果某个键的值不适用于活动区域设置,则会返回默认区域设置的值。
  • 如果默认语言环境的值也不可用,则返回任何其他语言环境的值。

我想出了一个非常尴尬的查询,可以达到预期的结果。假设店铺ID为1,表为Products,ID为gadget1;默认区域设置为en_AU,活动区域设置为de_DE。以下是我们要查询的内容:

SELECT * FROM 
    (SELECT `key`, `value` 
    FROM nf_CustomFields 
    WHERE `storeId` = 1
        AND `table` = 'Products'
        AND `id` = 'gadget1'
    ORDER BY `locale`='de_DE' DESC, 
        `locale`='en_AU' DESC
    ) 
AS a 
GROUP BY `key`;

这行得通,但它很难看,而且似乎效率低下。我知道有更好的方法,但我无法确定。

有人能推荐更好的吗?

非常感谢!

【问题讨论】:

  • 我过去做过类似的事情。不过我的设置有点不同:每件事都有其原始/默认语言,然后是一组翻译。这样一来,您就没有第三个选择,要么是他们的语言,要么是他们获得物品的母语。 OTOH,en_AU 在英国确实有一定的吸引力:)
  • 好吧,事实证明我正在做的是最好的事情。那好吧。一个人可以做梦。

标签: mysql syntax localization subquery


【解决方案1】:

您可以尝试 LEFT JOINing nf_CustomFields 到自身,然后使用 COALESCE 来忽略 LEFT JOIN 将在没有母语行时产生的 NULL。像这样的查询(未经测试,可能不工作):

select coalesce(nl.`key`,   def.`key`),
       coalesce(nl.`value`, def.`value`)
from nf_CustomFields nl
left outer join nfCustomFields def
     on nl.`store`  = def.`store`
    and nl.`table`  = def.`table`
    and nl.`id`     = def.`id`
    and nl.`locale` = 'de_DE'
 where def.`locale` = 'en_AU'
   and def.`id`     = KNOWN
   and def.`store`  = KNOWN
   and def.`table`  = KNOWN

KNOWN 当然会替换为您的已知值,并且您当然会使用实际动态值来代替 'de_DE''en_AU'

【讨论】:

  • 有趣的想法。我会试一试,但我不确定它是否允许 C 计划(回退到任何可用的语言环境)。干杯!
  • @Neil:我很确定您可以扩展该方法以允许“任何可用的语言”的东西。另一个 LEFT JOIN,重新调整连接条件和 WHERE,并将另一列添加到 COALESCE 调用。它不会很漂亮,但它应该可以使用适当的索引工作并正常执行。
  • 谢谢伙计。我会做一些基准测试并回复你:)
  • 这比我原来的效率要低一些,但由于没有其他想法,我会接受它,因为我认为这是一个很好的、有创意的想法:)
  • @Neil:如果您有更好的选择,您可以回答自己的问题并接受该答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多