Выборка только одного или другого значения из связной таблицы

Setor

Новичок
Выборка только одного или другого значения из связной таблицы

Задача заключается в следующем: есть мультиязычный каталог (табл. catalog), каждому элементу каталога соответствует хотябы одно название на одном из имеющихся языков (табл. catalog_lang). Обязательно существует название на английском и может существовать название на текущем языке. Требуется 1м запросом с объединением этих таблиц выбрать группу каталогов с названиями в приоритете на текущем языке, или если таковых не будет - на английском.

Таблица catalog:
categories_id | section_id

1 | 1
2 | 1
3 | 2

Таблица catalog_lang:
id | categories_id | languages_id | categories_name

1 | 1 | 0 | Computers
2 | 1 | 1 | Компьютеры
3 | 2 | 0 | Monitors

После выборки с условием section_id = 1 и ( languages_id = 1 или languages_id = 0 ) должно получиться:

section_id | categories_id | languages_id | categories_name

1 | 1 | 1 | Компьютеры
1 | 2 | 0 | Monitors

Обычный OR в таком случае будет выбирать всё подряд, а последующая группировка GROUP BY не поддаётся контролю и оставить из сгруппированного множества запись приоритетно на выбранном языке не представляется мне возможным. Только если предварительно отсортировать результат выборки по categories_id и languages_id во временную таблицу и с ней уже делать группировку, тогда гипотетически после группировки будет оставлен первый (верхний) элемент из группируемого множества. (например, двойным селектом в одном запросе) MySQL >= 4.1

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

Может есть ещё какие-то варианты?
 

vovik

Новичок
Могу предложить такой вариант.

PHP:
SELECT
c.section_id,
IFNULL(ru.name, en.name)
FROM catalog AS c
LEFT JOIN catalog_lang AS ru ON (ru.categories.id = c.categories_id AND en.languages_id = 1)
LEFT JOIN catalog_lang AS en ON (en.categories.id = c.categories_id AND en.languages_id = 0)
 

Setor

Новичок
Спасибо, интересный вариант. Но я потестировал и мой вариант оказался в пару раз шустрее (15ms против 30 на дереве 500 элементов и 800 мультиязычных названий), хотя, в твоём примере Explain выдавал более красивые цифры, но это было обусловлено тем, что у меня ещё используется группировка результатов. Позже этот метод будет использован на таблицах с более 100 тыс. записей в каждой, по этому хочется найти более оптимальный вариант.

Извлекается определённая ветка из дерева Nested Seets. Везде используются индексы.
PHP:
SELECT categories_id, languages_id, categories_name
FROM
(
    SELECT OC.categories_id, OC.left_key, OCD.languages_id, OCD.categories_name
    FROM catalog OC, catalog_lang OCD
    WHERE OC.`left_key` >= 6 AND OC.`right_key` <= 135 AND OC.`categories_id` = OCD.`categories_id` AND
         ( OCD.languages_id = 1 OR OCD.languages_id = 0 )
    ORDER BY OCD.categories_id, OCD.languages_id DESC
) AS lang_result
GROUP BY categories_id
ORDER BY left_key
 

Ansagan

Новичок
a kak stroyitsya sxema?

a kak stroyitsya sxema multiyazi4nogo sayta na php?
naprimer dopustim ya hoschu sozdat sayt na treh yazikah
dopustim s glavnoy stranisi po vidvejnomu menu ya popala na druguyu strani4ku i tut zahotela etu stranisu po4itat na english.
na kajdom yazike ya sozdam otdelniy sayt i postavlyu ssilku na index.php no kak svyazat do4ernuyu strani4ku odnogo yazika s ego je perevodom? plz sro4no help
 

x13

Guest
Re: a kak stroyitsya sxema?

Автор оригинала: Ansagan
a kak stroyitsya sxema multiyazi4nogo sayta na php?
naprimer dopustim ya hoschu sozdat sayt na treh yazikah
dopustim s glavnoy stranisi po vidvejnomu menu ya popala na druguyu strani4ku i tut zahotela etu stranisu po4itat na english.
na kajdom yazike ya sozdam otdelniy sayt i postavlyu ssilku na index.php no kak svyazat do4ernuyu strani4ku odnogo yazika s ego je perevodom? plz sro4no help
Либо использовать шаблоны для каждого языка. . .
Либо GetText'om. . .
 
Сверху