подскажите с запросом вроде не сложный .... но ре работает как надо

  • Автор темы Автор темы texrdcom
  • Дата начала Дата начала

texrdcom

Новичок
подскажите с запросом вроде не сложный .... но ре работает как надо

есть таблица:
PHP:
CREATE TABLE `test` (
  `id` int(10) NOT NULL auto_increment,
  `idpage` int(10) NOT NULL default '0',
  `lang` varchar(2) NOT NULL default '',
  `tekst` varchar(255) NOT NULL default '',
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;

-- 
-- Дамп данных таблицы `test`
-- 

INSERT INTO `test` VALUES (1, 2, 'ru', 'Рус');
INSERT INTO `test` VALUES (2, 2, 'ua', 'укр');

Таблица хранит Различные языковые версии для страници
которая определенна: idpage.

По умолчанию язык в системе ru - столбец lang

Собстенно запрос - в котром нужно получить запись с таблици
tekst на Укр ua - если записи нет то запрос должен вернуть запись на ru - на языке по умолчанию.

Вот запрос но он не работает как надо возвращает две записи хотя ожидаем одну!


PHP:
SELECT * FROM `test`
WHERE `idpage` = '2'
AND (
`lang` = 'ua'
OR `lang` = 'ru'
)

Возвращает две запси так как в таблице есть и запись с языком ua и с языком ru
Хотя ожидалось получить только запись с lang=ua
 
интересно... выбираем записи с idpage равным 2 (а он равен 2 у обоих записей) а ожидаем одну. Чудеса...
 
Gorynych
Да Вы правы у них одинаковый idpage потому что
это один элемент но с различными языковыми версиями
у них одинаковый idpage но различный lang!
Плюс у них различный id.
Что Вас в этом смутило или Вы просто не поняли вопроса,
и просто так пишите ?

P/s
Мой запрос не верен 100% Я это понимаю достаем
idpage =2 получаем две записи, вопрос в слудуещм как его исправить
для выше поставленной задачи,
возможно и перестроить тадлицы не проблема,
где то читал про метод где в одном большом поле text записываются различные
языковые версии разделенные например ###ru###рус ###ru### ###ua### Укр ###ua###
После выборки через функцию ищем нужный текст для кадого поля, но сама идея не особо
нравиться хотя другого варианта не вижу пока.
 
запись 1 имеет idpage 2 и lang 'ru'
запись 2 имеет idpage 2 и lang 'ua'

запрос: выбрать записи у которых idpage 2 И (lang равен 'ru' ИЛИ 'ua")

какая запись по-вашему НЕ подходит под такой запрос? По-моему обе прекрасно подходят
 
Отредактировал ответ,
да я понимаю что подходят !!! как сделать правильно ?
 
texrdcom
либо делай 2 запроса в первом - выбираешь idpage + язык, потом по этим двум критериям делаешь запрос на выборку непосредственно данных
либо добавляешь подзапрос выполняющай аналогичные действия
 
zerkms
Да понимаю можно сделать запрос

1) Определям есть ли запись для языка для которго зарпшиваем
если да то окей если нет то получаем запись для языка по умолчанию.

Но ето примлемо если нужно получить одну запись! а если 100 записей ? сколька запрсов прийдеться сделать ??? :(

Еще есть вариант получить в одном запросе две верссии разнеся
по разным языковым таблицам записи

ps
Хотя этот вариант срабатывает только при том что есть запись на двух языках
PHP:
SELECT test_lang_ru.text AS text_ru, test_lang_ua.text AS text_ua
FROM `test` , test_lang_ru, test_lang_ua
WHERE test.idpage = '2'
AND (
test_lang_ru.idpage = test.idpage
OR test_lang_ua.idpage = test.idpage
)
LIMIT 0 , 30

-~{}~ 03.02.07 14:27:

Почему нет в запросах sql
конструкции типа if ($res === 0) $lang = $dafault;
:)
 
texrdcom
вынеси языки в отдельную таблу, в неё добавь поле priority. при выборке присоединяй эту таблу, группируй и получай MIN(`priority`)
делов то
всё это у тебя уложится в 2 запроса или 1 с подзапросом
 
texrdcom
а ты уже попробовал сам следовать моему совету с отдельной таблой и приоритетами языков?
 
да вот попытки - больше их назвать не могу
все равно не получается так как надо сначало определить
есть ли значение по языку который запрашиваем

Запрос:
PHP:
SELECT *
FROM `test` , lang_test
WHERE `test`.`langid` = lang_test.id
AND idpage = '2'
AND prior = (
SELECT min( prior )
FROM `test` , lang_test
WHERE `test`.`langid` = lang_test.id
AND `idpage`
IN ( 2 )
AND `langid`
IN ( 1, 2 ) )

Возвращает всегда с языком с найменьшим приоритетом,
а нужно чтоб возращал его только тогда когда нет запрашиваемого языка

Вот дамп таблиц:
PHP:
-- phpMyAdmin SQL Dump
-- version 2.6.4-pl4
-- http://www.phpmyadmin.net
-- 
-- Хост: localhost
-- Время создания: Фев 03 2007 г., 16:55
-- Версия сервера: 4.1.16
-- Версия PHP: 5.1.6
-- 
-- БД: `newcms`
-- 

-- --------------------------------------------------------

-- 
-- Структура таблицы `lang_test`
-- 

CREATE TABLE `lang_test` (
  `id` int(10) NOT NULL auto_increment,
  `prior` int(1) NOT NULL default '0',
  `lang` varchar(2) NOT NULL default '',
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;

-- 
-- Дамп данных таблицы `lang_test`
-- 

INSERT INTO `lang_test` VALUES (1, 1, 'ru');
INSERT INTO `lang_test` VALUES (2, 2, 'ua');

-- --------------------------------------------------------

-- 
-- Структура таблицы `test`
-- 

CREATE TABLE `test` (
  `id` int(10) NOT NULL auto_increment,
  `idpage` int(10) NOT NULL default '0',
  `langid` int(10) NOT NULL default '0',
  `text` varchar(255) NOT NULL default '',
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;

-- 
-- Дамп данных таблицы `test`
-- 

INSERT INTO `test` VALUES (3, 2, 1, 'Рус');
INSERT INTO `test` VALUES (2, 2, 2, 'Укр');
 
texrdcom
Возвращает всегда с языком с найменьшим приоритетом,
а нужно чтоб возращал его только тогда когда нет запрашиваемого языка
в запрос подключи ещё и CASE :)
 
zerkms
Спасибо за не медвежью помощь :)
Вот так все работает:
PHP:
SELECT *
FROM `test` , lang_test
WHERE `test`.`langid` = lang_test.id
AND idpage = '2'
AND prior = (
SELECT min( prior )
FROM `test` , lang_test
WHERE `test`.`langid` = lang_test.id
AND `idpage`
IN ( 2, 3, 4 )
AND `langid`
IN ( 1, 2 )
ORDER BY CASE WHEN langid = '1'
THEN 1
ELSE 2
END )
 
Собстенно запрос - в котром нужно получить запись с таблици
tekst на Укр ua - если записи нет то запрос должен вернуть запись на ru - на языке по умолчанию.

Вот запрос но он не работает как надо возвращает две записи хотя ожидаем одну!


PHP:
SELECT * FROM `test` 
WHERE `idpage` = '2' 
AND ( `lang` = 'ua'  OR `lang` = 'ru' ) 
AND tekst IS NOT NULL
GROUP BY idpage
Разве так не вернутся записи по lang` = 'ua' если они присутствуют? Разве, что lang` = 'ru' должно быть заполненно, иначе не вернется НИЧЕГО!
Или я не так понял задачу?
 
В догонку работает и без case он лишний :)
Просто нужно следовать првилу что язык по умолчанию имеет
приоритет найбольший в системе например 100
остальные языки могут иметь любой приоритет ниже 100,
в принцепе каждый другой язык может иметь приоритет например
1 - всегда выборка выполняеться между двумя языками 1) который запрашиваем - если нет то язык по умолчанию.
вот и запрос который работает коректно без case
PHP:
SELECT *
FROM `test` , lang_test
WHERE `test`.`langid` = lang_test.id
AND `idpage`
IN ( 2, 3, 4 )
AND `langid`
IN ( 1, 2 )
AND prior = (
SELECT min( prior )
FROM `test` , lang_test
WHERE `test`.`langid` = lang_test.id
AND `langid`
IN ( 1, 2 ) )

p/s
Написал пример так как считаю что не один задвался етим
вопросом, может кому поможет.
p/s p/s
Это не уменшает моей благодарности zerkms
:)

-~{}~ 04.02.07 16:31:

_Leonchik_
Нет так было бы очень просто :)
при наличии записи и на язык ru и на ua будет возвращенна запись
с первым по счету id а не по запришиваему языку !
Тоисть нуже приоритет языков - язык по умолчанию, язык для которого запрашиваем запись.
Например мы запрашиваем запись для языка ua если она есть то возвращаеться она, если нет то только в етом случаи возвращаеться запись на языке по умолчанию.

p/s
Легко можно выводить меню например сайта на различных языках, если какойто пункт не был переведен то выводиться
пункт на языке по умолчанию в системе, точно также можно выводить текст на страници если есть перевод возвращаеться он
нет выводиться текст орегинальной статьи.
 
texrdcom
Код:
SELECT *
FROM `page` p
  LEFT JOIN lang_test l1 ON l1.`idpage` = p.id AND l1.`lang` = 'ua' 
  LEFT JOIN lang_test l2 ON l2.`idpage` = p.id AND l2.`lang` = 'ru' AND l1.id IS NULL
 
Сверху