Задавайте вопросы, мы ответим
Вы не зашли.
Занимаюсь реализацией поиска на сайте.
На сайте есть справочник по фирмам города. Фирма может иметь прайс-лист, также у фирм есть рейтинг, который получается разностью положительный и отрицательных отзывов. Фирма состоит в подкатегориях, который в свою очередь состоят в категориях. Нарпимер категория "Сухопутный транспорт" может включать в себя подкатегории "мотоциклы", "легковые автомобили" и т.д. Подкатегория может быть включена либо в товары либо в услуги, это ещё одна связь подкатегорий. Связь всех таблиц я постарался изобразить на рисунке.
Долго думал над тем, как осущиствить поиск, но не придумал ничего лучше этой схемы:
Т.к. у фирм куча пораметров (адрес, телефон, е-маил, доаолнительный адрес, краткое описание и т.д.), решил создать таблицу, в одно поле которой собрать весь перечень возможных запросов по фирме. Это таблица "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
Неактивен
Такое количество таблиц мне не одолеть
Общий принцип я бы сделал такой: хранимая процедура, которая делает следующее.
1. Создает временную табличку с одним полем — целым числом — в него будут записываться
id фирм.
2. Из каждой таблички, по которой можно вести поиск, проводит поиск и записывает
соответствующие id во временную табличку.
3. Вытаскивает id из временной таблички, объединенной с табличкой фирм, в нужном порядке.
4. Убивает временную табличку.
Хотя, обычно поступают проще — человек знает, ищет он по названию улицы или по названию
фирмы. И может это указать как параметр поиска
P.S. Кстати, подумайте заранее о том, как будете бороться с проблемой вложенных подкатегорий
(например, мотоциклы разделятся на двухколесные и трехколесные )
Неактивен
1. ну временную табличку,как мне кажется создавать не нужно, он акак-бы создастся при запросе правильном.
2. Ваши рассуждения не лишены смысла, но фишка в том, что если совпадение найдено в названии категории, то выведется одна категория в столбце категорий и одна фирма, то есть все фирмы в категории, это более релевантно, нежели идущие после этого совпадения в конкретной фирме, в поле категория где несколько категорий.
3. Дать пользователю возможность выбират, где искать? Я и так предоставляю ему выбор, поиск в статьях, новостях, объявлениях и, собственно, в каталоге. Но пользователь глуп по природе, и не хочется его заставлять лишний раз подумать.
4. Вложенных подкатегорий не будет, все категории и подкатегории тщательно продумывались, учтено, мне кажется, всё, а уж вложенные подкатегории точно исключены.
Неактивен
А в чем тогда вопрос?
Неактивен
вопрос в том, как написать такой хитрый запрос
Неактивен
Почему Вы заботитесь о пользователе, почему Вы не заботитесь обо мне?
Не хотите со временной табличкой — напишите пачку коротких запросов через UNION,
и потом прицепите к этому конгломерату основную таблицу фирм. То же самое, только
без явного создания временной таблички. Т.е. будет что-то типа
SELECT ...
FROM ( SELECT firm_id FROM a WHERE ... UNION SELECT firn_id FROM b WHERE ... ) ids
JOIN firms USING (firm_id)
Неактивен