Использование подзапросов для резервирования локали в MySQL - PullRequest
2 голосов
/ 15 августа 2011

У меня есть продукт в интернет-магазине, который поддерживает настраиваемые поля для различных типов данных.Сокращение, чтобы погнать, любой может добавить дополнительные пары ключ / значение к любой записи, добавив в таблицу, которая определена как:

`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`)

В Европе многие люди хотят поддерживать несколько языков, поэтому каждый ключможет иметь несколько значений для разных локалей.У каждого магазина будет локаль по умолчанию (назначенная владельцем магазина) и активная локаль (выбранная клиентом).

Запрос, который я пытаюсь составить, ведет себя так:

  • Известны storeId, table и id, а также активная локаль и локаль по умолчанию.
  • Если значение для ключа недоступно для активной локали, значениевместо этого возвращается локаль по умолчанию.
  • Если значение для локали по умолчанию также недоступно, верните значение для любой другой локали.

Iпридумали довольно неловкий запрос, который достигает желаемого результата.Допустим, идентификатор магазина равен 1, таблица - Products, а идентификатор - 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`;

Это работает, но уродливо и кажется неэффективным.Я знаю, что есть лучший способ, но я не могу понять, на что он способен.

Кто-нибудь может предложить что-то лучше?

Большое спасибо!

1 Ответ

1 голос
/ 15 августа 2011

Вы можете попробовать LEFT JOINing nf_CustomFields к себе, а затем использовать COALESCE, чтобы игнорировать значения NULL, которые LEFT JOIN выдаст, если строк на родном языке нет. Примерно такой (непроверенный и, возможно, не работающий) запрос:

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', конечно.

...