Модераторы: skyboy
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> выборка записей из таблицы локализации 
:(
    Опции темы
Greengerty
Дата 4.9.2015, 22:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 31.1.2012

Репутация: нет
Всего: нет



Всем привет,

 возникла задача 
есть 2 таблицы: countries и countries_languages
мне на вход поступает параметр языка например "ru",
 и я должен получить все страны с языком ru
причем если нет языка выводить тот что по умолчанию стоит английский
задача состоит в том что бы решить все это одним запросом

вот как я думал это реализовать http://sqlfiddle.com/#!9/eff6e/1

вот тестовые данные и запрос что делал

CREATE TABLE IF NOT EXISTS `countries` (
`id` int(10) unsigned NOT NULL,
  `iso` varchar(2) NOT NULL,
  `popular` int(11) DEFAULT NULL,
  `status` enum('public','draft') NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=387 ;

CREATE TABLE IF NOT EXISTS `countries_languages` (
`id` int(10) unsigned NOT NULL,
  `country_id` int(11) NOT NULL,
  `language` varchar(2) NOT NULL,
  `title` varchar(72) NOT NULL,
  `meta_keywords` text,
  `meta_description` text,
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=2719 ;

ALTER TABLE `countries`
 ADD PRIMARY KEY (`id`);
ALTER TABLE `countries_languages`
 ADD PRIMARY KEY (`id`);

INSERT INTO `countries` (`id`, `iso`, `popular`, `status`, `created_at`, `updated_at`) VALUES
(1, 'al', NULL, 'public', '0000-00-00 00:00:00', '0000-00-00 00:00:00'),
(2, 'ad', NULL, 'public', '0000-00-00 00:00:00', '0000-00-00 00:00:00'),
(3, 'ar', NULL, 'public', '0000-00-00 00:00:00', '0000-00-00 00:00:00');

INSERT INTO `countries_languages` (`id`, `country_id`, `language`, `title`, `meta_keywords`, `meta_description`, `created_at`, `updated_at`) VALUES
(1, 1, 'en', 'Albania', NULL, NULL, '0000-00-00 00:00:00', '0000-00-00 00:00:00'),
(2, 2, 'en', 'Andorra', NULL, NULL, '0000-00-00 00:00:00', '0000-00-00 00:00:00'),
(3, 3, 'en', 'Argentina', NULL, NULL, '0000-00-00 00:00:00', '0000-00-00 00:00:00'),
(2257, 1, 'ru', 'Албания', NULL, NULL, '0000-00-00 00:00:00', '0000-00-00 00:00:00'),
(2259, 3, 'ru', 'Аргентина', NULL, NULL, '0000-00-00 00:00:00', '0000-00-00 00:00:00');

сам запрос
select * from
  (
select * from `countries` 
  left join `countries_languages` as `ml` on `countries`.`id` = `ml`.`country_id` and `ml`.`language` = 'ru'
  ) as t1
  
  join `countries_languages` as `ml` on `t1`.`id` = `ml`.`country_id` and `ml`.`language` = 'en'
этот запрос выдает ошибку "Duplicate column name 'id'"

может кто то знает простое и элегантное решение данной задачи?
PM MAIL   Вверх
jsharp36
Дата 5.9.2015, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 8.10.2011

Репутация: нет
Всего: 1



Логика где-то верная - один join и один left join. Только намудрено с внутренним запросом. То, что в скобках, SQL пытается объеднить в таблицу, а в ней дублируются колонки, что для таблицы нельзя. Т.е. во внутреннем запросе нельзя изпользовать *. В данном случае там оказываются две колонки id. Из таблицы `countries` и `countries_languages`. Явно перечислите колонки и будет запрос работать.

Может мало понял, что вы хотите, но как понял, запрос проще:

select c.`id`, c.`iso`,
      case when cl.`id` is not null then cl.`language`
           else dcl.`language` end as `language` from `countries` as c
join `countries_languages` as dcl on c.`id` = dcl.`country_id` and dcl.`language` = 'en'
left join `countries_languages` as cl on c.`id` = cl.`country_id` and cl.`language` = 'ru'

Еще, у вас странная структура таблиц. Неправильная. Таблица `countries_languages` должна исходя из названия хранить языки стран. А в ней в колонке title находятся названия стран. А в таблице стран `countries` названий стран нет.


Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
Greengerty
Дата 5.9.2015, 17:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 31.1.2012

Репутация: нет
Всего: нет



спасибо, 

логика таблиц такая
countries - в ней хранится все то что не требует перевода
countries_languages - в ней хранится все что требует перевода и язык локали, в будущем возможно будут храниться language_id из таблицы languages, вместо локали

languages - в ней хранятся все языки
PM MAIL   Вверх
Akina
Дата 5.9.2015, 20:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 45
Всего: 454



Цитата(Greengerty @  4.9.2015,  23:20 Найти цитируемый пост)
если нет языка выводить тот что по умолчанию стоит английский

Переведите ЭТО на русский...

А вообще запрос должен быть типа 
Код

SELECT 
  c.id    /*
, ...       */
, c.updated_at
, cl.id    /*
, ...      */
, COALESCE(cl.language,'en') language    /*
, ...     */
, cl.updated_at
FROM countries c
LEFT JOIN countries_languages as cl 
  ON c.id = cl.country_id AND cl.language = 'ru'

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

Добавлено через 1 минуту и 18 секунд
PS. Давая ссылки на sqlfiddle - проверяйте своё творчество ТАМ.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
jsharp36
Дата 5.9.2015, 23:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 8.10.2011

Репутация: нет
Всего: 1



да, Akina, ваш запрос на этих данных тоже верный, если задача не четко описана ) И он проще. Но он глупый так же как и мой.
Мой запрос - просто шаблон, который можно расширять. Вообще, скорее всего, для будущей задачи надо не 'en', 'ru' выводить, а language_id. Мой запрос не вернет английский для страны, у которой нет английского. Т.е. если будут такие данные. Ваш вернет любой стране 'en', даже если нет записей.


Мой запрос - шаблон, который можно расширять. Но если задача практическая, то:
case when cl.`id` is not null then cl.`language`
           else dcl.`id` end as dcl.`id`
надо поменять и использовать как вьюху или функцию как внутренний подзапрос.


Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
Greengerty
Дата 6.9.2015, 15:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 31.1.2012

Репутация: нет
Всего: нет



классное решение
Цитата

case when cl.`id` is not null then cl.`language`
           else dcl.`id` end as dcl.`id`
 

спасибо
PM MAIL   Вверх
jsharp36
Дата 6.9.2015, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 4
Регистрация: 8.10.2011

Репутация: нет
Всего: 1



case when cl.`id` is not null then cl.`language`
           else dcl.`language` end as `language`

Вот так надо ) Может я с  багом отсылал, потом поправил.

На самом деле это стандартное решение, как сделать одну колонку из нескольких таблиц по некоторым условиям

Этот ответ добавлен с нового Винграда - http://vingrad.com
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




[ Время генерации скрипта: 0.0720 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.