SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 15.04.2009 10:39:22

NCIAC
Участник
Зарегистрирован: 07.02.2009
Сообщений: 7

Объединение таблиц для поиска по сайту

Занимаюсь реализацией поиска на сайте.
На сайте есть справочник по фирмам города. Фирма может иметь прайс-лист, также у фирм есть рейтинг, который получается разностью положительный и отрицательных отзывов. Фирма состоит в подкатегориях, который в свою очередь состоят в категориях. Нарпимер категория "Сухопутный транспорт" может включать в себя подкатегории "мотоциклы", "легковые автомобили" и т.д. Подкатегория может быть включена либо в товары либо в услуги, это ещё одна связь подкатегорий. Связь всех таблиц я постарался изобразить на рисунке.

Долго думал над тем, как осущиствить поиск, но не придумал ничего лучше этой схемы:
Т.к. у фирм куча пораметров (адрес, телефон, е-маил, доаолнительный адрес, краткое описание и т.д.), решил создать таблицу, в одно поле которой собрать весь перечень возможных запросов по фирме. Это таблица "index".
Допустим пользователь ввёл "транспорт". Тогда должны вывестись все фирмы, которые состоят в подкакатегории, принадлежащей категории, в названии или описании которой есть слово "транспорт". Если же фирма находится на улице Транспортной, то эта фирма тоже должна вывестись. Причём вывод должен иметь следующий вид:
| Категория | Фирма | Рейтинг фирмы |
Естественно, фирма, находящаяся на улице Транспортной, может состоять в нескольких категориях, тогда в графе "категория" нужно вывести все эти категории через запятую.
Ну и самое интересное, при выводе должно учитываться в первую очередь наличие прайса, во вторую рейтинг. То есть сначала выводятся все фирмы с прайсами, между совой они выстраиваются в зависимости от рейтинга, потом идут фирмы бес прайса и тоже идут в зависимости от рейтинга. Прайсов у фирмы может быть несколько, выбирается последний. В каталоге есть ещё частные бригады, поэтому где есть prenadl, он лдолжен быть равен 'f' для фирм, 'b' для бригад.

Таблицы:
CREATE TABLE `firms` (
  `id` int(25) NOT NULL auto_increment,
  `name` varchar(100) default NULL,

  ***
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=225 DEFAULT CHARSET=cp1251 AUTO_INCREMENT=225 ;

CREATE TABLE `index` (
  `idindex` int(255) NOT NULL auto_increment,
  `firmbrid` int(255) NOT NULL,
  `prenadl` varchar(2) NOT NULL,
  `text` text NOT NULL,
  PRIMARY KEY  (`idindex`)
) ENGINE=MyISAM AUTO_INCREMENT=3 DEFAULT CHARSET=cp1251 AUTO_INCREMENT=3 ;

CREATE TABLE `resp` (
  `id` int(10) NOT NULL auto_increment,
  `znach` int(1) NOT NULL,
  `comment` text,
  `firm_br_id` int(255) NOT NULL,
  `prenadl` varchar(2) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=177 DEFAULT CHARSET=cp1251 AUTO_INCREMENT=177 ;

CREATE TABLE `temp_price` (
  `id` int(255) NOT NULL auto_increment,
  `filename` varchar(255) NOT NULL,
  `firm_id` int(255) NOT NULL,
  `time` datetime NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=cp1251 AUTO_INCREMENT=6 ;

CREATE TABLE `podcat_firms` (
  `id` int(255) NOT NULL auto_increment,
  `podcat_id` int(255) NOT NULL,
  `firms_id` int(255) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=160 DEFAULT CHARSET=cp1251 AUTO_INCREMENT=160 ;

CREATE TABLE `podcat` (
  `id` int(255) NOT NULL auto_increment,
  `name` varchar(255) NOT NULL,
  `ind` text NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=149 DEFAULT CHARSET=cp1251 AUTO_INCREMENT=149 ;

CREATE TABLE `cat_podcat` (
  `id` int(11) NOT NULL auto_increment,
  `cat_id` int(11) NOT NULL,
  `podcat_id` int(11) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=173 DEFAULT CHARSET=cp1251 AUTO_INCREMENT=173 ;

CREATE TABLE `cat` (
  `id` int(255) NOT NULL auto_increment,
  `name` varchar(255) NOT NULL,
  `description` varchar(255) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=53 DEFAULT CHARSET=cp1251 AUTO_INCREMENT=53 ;

CREATE TABLE `podcat_glava` (
  `id` int(255) NOT NULL auto_increment,
  `podcat_id` int(10) NOT NULL,
  `glava_id` int(10) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=360 DEFAULT CHARSET=cp1251 AUTO_INCREMENT=360 ;

CREATE TABLE `glava` (
  `id` int(255) NOT NULL auto_increment,
  `name` varchar(20) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=cp1251 AUTO_INCREMENT=4 ;

Для просто вывода в каталоге используется следующий запрос, написаный не мной, может пригодятся:

SELECT DISTINCT firms_temp.* FROM (SELECT f.*, (prt IS NOT NULL) AS ppl, COALESCE(rat,0) AS rats
FROM firms AS f
LEFT JOIN (SELECT firm_id, MAX(time) as prt FROM temp_price GROUP BY firm_id) AS pl 
ON f.id = pl.firm_id 
LEFT JOIN (SELECT firm_br_id, SUM(znach*2-3) AS rat FROM resp WHERE `prenadl` = 'f' GROUP BY firm_br_id) AS rt
ON f.id = rt.firm_br_id 
ORDER BY ppl DESC, rats DESC, name ) AS firms_temp, podcat_firms, cat_podcat, podcat_glava
WHERE firms_temp.id=podcat_firms.firms_id
AND podcat_firms.podcat_id=cat_podcat.podcat_id
AND cat_podcat.cat_id=$cat_id
AND cat_podcat.podcat_id=podcat_glava.podcat_id
AND podcat_glava.glava_id=$n
ORDER BY firms_temp.ppl DESC, firms_temp.rats DESC, firms_temp.name


Прикрепленные файлы:
Attachment Icon tables.gif, Размер: 33,068 байт, Скачано: 508

Неактивен

 

#2 15.04.2009 22:30:53

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6756

Re: Объединение таблиц для поиска по сайту

Такое количество таблиц мне не одолеть wink

Общий принцип я бы сделал такой: хранимая процедура, которая делает следующее.
1. Создает временную табличку с одним полем — целым числом — в него будут записываться
id фирм.
2. Из каждой таблички, по которой можно вести поиск, проводит поиск и записывает
соответствующие id во временную табличку.
3. Вытаскивает id из временной таблички, объединенной с табличкой фирм, в нужном порядке.
4. Убивает временную табличку.

Хотя, обычно поступают проще — человек знает, ищет он по названию улицы или по названию
фирмы. И может это указать как параметр поиска smile

P.S. Кстати, подумайте заранее о том, как будете бороться с проблемой вложенных подкатегорий
(например, мотоциклы разделятся на двухколесные и трехколесные wink )

Неактивен

 

#3 16.04.2009 01:12:23

NCIAC
Участник
Зарегистрирован: 07.02.2009
Сообщений: 7

Re: Объединение таблиц для поиска по сайту

1. ну временную табличку,как мне кажется создавать не нужно, он акак-бы создастся при запросе правильном.
2. Ваши рассуждения не лишены смысла, но фишка в том,  что если совпадение найдено в названии категории, то выведется одна категория в столбце категорий и одна фирма, то есть все фирмы в категории, это более релевантно, нежели идущие после этого совпадения в конкретной фирме, в поле категория где несколько категорий.
3. Дать пользователю возможность выбират, где искать? Я и так предоставляю ему выбор, поиск в статьях, новостях, объявлениях и, собственно, в каталоге. Но пользователь глуп по природе, и не хочется его заставлять лишний раз подумать.
4. Вложенных подкатегорий не будет, все категории и подкатегории тщательно продумывались, учтено, мне кажется, всё, а уж вложенные подкатегории точно исключены.

Неактивен

 

#4 16.04.2009 15:43:06

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6756

Re: Объединение таблиц для поиска по сайту

А в чем тогда вопрос? wink

Неактивен

 

#5 16.04.2009 16:28:39

NCIAC
Участник
Зарегистрирован: 07.02.2009
Сообщений: 7

Re: Объединение таблиц для поиска по сайту

вопрос в том, как написать такой хитрый запрос

Неактивен

 

#6 16.04.2009 16:45:25

paulus
Администратор
MySQL Authorized Developer and DBA
Зарегистрирован: 22.01.2007
Сообщений: 6756

Re: Объединение таблиц для поиска по сайту

Почему Вы заботитесь о пользователе, почему Вы не заботитесь обо мне? smile

Не хотите со временной табличкой — напишите пачку коротких запросов через UNION,
и потом прицепите к этому конгломерату основную таблицу фирм. То же самое, только
без явного создания временной таблички. Т.е. будет что-то типа
SELECT ...
FROM ( SELECT firm_id FROM a WHERE ... UNION SELECT firn_id FROM b WHERE ... ) ids
JOIN firms USING (firm_id)

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson