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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Сортировка 
V
    Опции темы
starmaster
Дата 20.12.2007, 01:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



У меня такой вопрос. Есть таблица, например, такого содержания:

ID  fname    likes               
1   Андрей  Комедии|Боевики|Драмы    
2   Дима      Триллеры|Боевики|Эротика 
3   Олег      Драмы|Комедии|Триллеры   
4   ...           ...                      
5   ...           ...      

Нужно отсортировать имена, к примеру, по Боевикам в алфавитном порядке. В поле likes, чёрточка | - разделитель между жанрами. Имена в поле fname уникальны. Можно  ли как-нибудь отсортировать запросом или всё же лучше создать другую таблицу, где вписывать каждый  жанр с именем в отдельную запись?               
PM MAIL WWW ICQ   Вверх
SelenIT
Дата 20.12.2007, 01:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


баг форума
****


Профиль
Группа: Завсегдатай
Сообщений: 3996
Регистрация: 17.10.2006
Где: Pale Blue Dot

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



starmaster, уточните вопрос. Нужно выбрать записи, где в значение likes входят Боевики, и отсортировать их по именам?


--------------------
Осторожно! Данный юзер и его посты содержат ДГМО! Противопоказано лицам с предрасположенностью к зонеризму!
PM MAIL   Вверх
starmaster
Дата 20.12.2007, 01:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Ну типа: 
Боевики -> Андрей, Дима
Комедии -> Андрей, Олег

То есть да, найти имена на каждый жанр и отсортировать их.
PM MAIL WWW ICQ   Вверх
skyboy
Дата 20.12.2007, 01:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

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



в корне неверный подход. ибо чреват неприятностями, не давая никаких преимуществ. ни в скорости, ни в гибкости.
вот, смотри:
проблема 1 связана с тем, что если текстовые идентификаторы интересов вводятся вручную, то нельзя гарантировать их корректность. например, человек может ввести "беовик". и что - сразу увидишь? если же вводить значения из списка, а после выбора вставлять соответствующую строку, то возникает проблема 2, которая связана с избыточностью данных. т.е. если для 100 человек задать интерес "мистический триллер", то объем хранимой информации для жанров составит 1900 байт текста. на голом месте. проблема 3 связана с производительностью. запросы с группировкой при такой структуре вообще нереальны(к примеру, сколько имеется имеется человек с интересом "эротика"?). запросы поиска(один из которых ты ожидаешь получить) будут использовать поиск по текстовому полю, что в жизни не составит конкуренцию поиску по числовому значению.
итог: приведи БД к нормальной форме. Для этого выдели названия интересов в отдельную таблицу(idHobby - autoincrement и name - varchar), отдельно у тебя будут люди(idman -autoincrement и другие необходимые тебе поля. и отдельно таблица men_hobbies всего из двух полей: idman и idHobby.
--
для твоей задачи решение в использовании функции locate 
Код

SELECT `fname`,`likes`
FROM `table`
WHERE LOCATE('боевик',`likes`)> 0
ORDER BY `fname` 

правда, в общем виде запрос не совсем корректен, так как найдет и записи с "боевик", и со значением "комедийный боевик". если надо, чтоб "боевик" нашло, а "комедийный боевик" - нет, можно использовать конструкцию
Код

SELECT `fname`,`likes`
FROM `table`
WHERE LOCATE('|боевик|',concat('|',concat(`likes`,'|')))> 0
ORDER BY `fname` 


Добавлено через 52 секунды
Цитата(starmaster @  20.12.2007,  00:22 Найти цитируемый пост)
То есть да, найти имена на каждый жанр и отсортировать их. 

вон оно как уже перевернулось...

Добавлено через 2 минуты и 29 секунд
Цитата(starmaster @  20.12.2007,  00:22 Найти цитируемый пост)
То есть да, найти имена на каждый жанр и отсортировать их. 

если ты сам определишь полный список интересов в коде - такое возможно, хоть и коряво будет. если надеешься, что оно само тебе сгруппирует для каждой заключенной между "|" строки, то такое без нормализации невозможно.
PM MAIL   Вверх
starmaster
Дата 20.12.2007, 02:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



На самом деле я довольно часто сталкиваюсь с такими задачами, когда для одной какой-то записи существует несколько других записей, которые потом повторяются для других записей, типа первой и надо отсортировать первые записи по одной из этих нескольких других. Всё верно, второй твой код sql полностью решает мою задачу, ты даже прочитал мои мысли (я хотел здесь добавить), что Комедия не тоже самое, что Новогодняя комедия. Но вот, я нормализовал по твоему совету таблицу, получилось к примеру: 

1) Таблица интересов hobbies

idhobby   hobbyname
1               Комедии
2               Боевики
3               Эротика

2) Таблица имён men_names

idman     manname
1               Андрей
2               Дима
3               Олег

3) Таблица совместимостей men_hobbies

idman     idhobby
1                2
1                3
2                1
3                1
3                2
3                3

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

А раньше решал задачу (из моего варианта таблицы) примерно так:

Код

select fname from tablename where likes like "%Комедии%"  order by fname asc;


Но ты прав, существуют намного лучше варианты, вот про них я в общем-то и хотел узнать...
PM MAIL WWW ICQ   Вверх
SelenIT
Дата 20.12.2007, 10:10 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


баг форума
****


Профиль
Группа: Завсегдатай
Сообщений: 3996
Регистрация: 17.10.2006
Где: Pale Blue Dot

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



Код

SELECT h.hobbyname, mn.manname
FROM men_names mn
INNER JOIN men_hobbies mh USING idman
INNER JOIN hobbies h USING idhobby
ORDER BY h.hobbyname, mn.manname

подойдет?


--------------------
Осторожно! Данный юзер и его посты содержат ДГМО! Противопоказано лицам с предрасположенностью к зонеризму!
PM MAIL   Вверх
Akina
Дата 20.12.2007, 10:45 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(starmaster @  20.12.2007,  03:19 Найти цитируемый пост)
я довольно часто сталкиваюсь с такими задачами, когда для одной какой-то записи существует несколько других записей, которые потом повторяются для других записей, типа первой и надо

Совершенно стандартная задача построения связи типа многие-ко-многим.

Цитата(starmaster @  20.12.2007,  03:19 Найти цитируемый пост)
Какой теперь предложишь код для того, чтобы решить эту задачу?

Которую именно? Если выбрать, скажем, тех, кого колбасит от комедий, то

Код

select `men_names`.`manname`
from `men_names`
  inner join `men_hobbies`
  on `men_names`.`idman` = `men_hobbies`.`idman`
where `men_hobbies`.`idhobby` = 1



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

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


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

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



Цитата(starmaster @  20.12.2007,  01:19 Найти цитируемый пост)
Но ты прав, существуют намного лучше варианты, вот про них я в общем-то и хотел узнать...

вот ты и узнал smile
хочу еще заметить, что нормальную форму(которая теперь уже имеется у тебя) запросто можно привести к денормальной, используя group_concat
т.е. можно сделать так:
Код

SELECT `h`.`hobbyname`,group_concat(`mn`.`name` ORDER BY `mn`.`name`) 
FROM `men_names` `m`
INNER JOIN `men_hobbies` `mh`
OM `mh`.`idman` = `mn`.`idman`
INNER JOIN `hobbies` `h`
ON `h`.`idhobby` = `mh`.`idhobby`
GROUP BY `h`.`idhobby`,`h`.`hobbyname`

должно выдать тебе для каждого  хобби список людей, предпочитающих его, через запятую с сортировкой по имени.
можно так же свернуть три таблицы до выборки, с результатом, идентичным твоему первоначальному варианту. я к тому, что данные в нормальной форме можно денормализовывать. а наоборот - функций соотвествующих нет(чтоб функция получала на вход строку и разделитель, а на выходе - временную таблицу - аналог РНР функции explode)
PM MAIL   Вверх
starmaster
Дата 20.12.2007, 23:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Спасибо заранее, но вот, чтобы совсем стало понятно по этой задаче, можно ли как-нибудь удалить одним запросом имена в таблице men_names, которые увлекаются комедиями, к примеру? Всё такая же задача, но как будет в случае с удалением?
PM MAIL WWW ICQ   Вверх
Akina
Дата 20.12.2007, 23:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(starmaster @  21.12.2007,  00:08 Найти цитируемый пост)
можно ли как-нибудь удалить одним запросом имена в таблице men_names, которые увлекаются комедиями

Код

delete `men_names`
from `men_names`, `men_hobbies`
where `men_names`.`idman` = `men_hobbies`.`idman`
   and `men_hobbies`.`idhobby` = 1



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

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


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

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



Код

DELETE `mn`.*[,`mh`.*]
FROM `men_names` `mn`, `hobbies` `h`,`men_hobbies` `mh` 
WHERE `h`.`hobbyname` = 'комедия' AND `mh`.`idhobby` = `h`.`idhobby` AND `mn`.`idman` = `mh`.`idman`

то, что внутри квадратных скобок необходимо только в случае, если отсутствуют внешние ключи/триггеры на удаление с men_hobbies на men_names. в противном случае эта часть пригодится.
P.S. Описание синтаксиса DELETE можно посмотреть в online-руководстве.
PPS Надеюсь, ничего не попутал. Сам такие конструкции делал пару раз в жизни(в смылсе - редко попадались запросы, когда надо удалить сущность из-за связей с другой сущностью), потому в приведенном коде могут оказаться недочеты. но дух передал правильно smile

Добавлено через 44 секунды
Цитата(skyboy @  20.12.2007,  22:45 Найти цитируемый пост)
то, что внутри квадратных скобок

в любом случае, квадратные скобки просто для указания необязательной части. из кода при выполнении они в любом случае должны быть выброшены.
PM MAIL   Вверх
starmaster
Дата 21.12.2007, 00:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(Akina @  20.12.2007,  10:45 Найти цитируемый пост)
Совершенно стандартная задача построения связи типа многие-ко-многим.


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

Цитата(skyboy @  20.12.2007,  11:08 Найти цитируемый пост)
аналог РНР функции explode


Именно с PHP всё это и использую.

Короче нужно учить построение более сложных запросов smile

skyboy, Akina, SelenIT

Спасибо!

Это сообщение отредактировал(а) starmaster - 21.12.2007, 00:44
PM MAIL WWW ICQ   Вверх
vi_k
Дата 31.12.2007, 07:37 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



2skyboy:

Простите, что вмешиваюсь. Всё нравится, всё замечательно. Один маленький нюанс:

Код

... concat('|',concat(`likes`,'|')) ...


concat может принимать несколько аргументов. Поэтому можно заменить на:
Код

... concat('|',`likes`,'|') ...

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | MySQL | Следующая тема »


 




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


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

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