Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Поиск по двум связанным таблицам
Форумы портала PHP.SU » PHP » SQL и Архитектура БД » Поиск по двум связанным таблицам

Страниц (1): [1]
 

1. Serpanok - 10 Октября, 2017 - 15:13:24 - перейти к сообщению
Добрый день!

У меня есть две таблицы "Улицы" и "Строения". Строения привязаны к "Улицам" Необходимо осуществить поиск нужного строения имея поисковой запрос в виде текста(если поисковой запрос не точен - можно несколько результатов).
У строк есть так же "алиасы", те разные вариации написания(title: Чапаева, sub_titles: Кирова|Пушкина), те улица может иметь синонимы в названии.(формат хранения алиасов может быть любой, как вы скажете так и буду хранить).

Например: "Чапаева 14", "Чапаева", "улица Чапаева 14", "14 Чапаева" итд

`streets` (
`street_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL,
`sub_titles` varchar(255) DEFAULT NULL,
PRIMARY KEY (`street_id`)
);
`locations` (
`location_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`street_id` smallint(5) unsigned DEFAULT NULL,
`title` varchar(100) NOT NULL,
PRIMARY KEY (`location_id`)
);

Нужно получить идентификаторы строений подходящих под поисковой запрос.

Пригодится любая помощь и советы. Даже просто описание запроса на "человеческом" языке, попробую если что сам его составить.
2. LIME - 10 Октября, 2017 - 15:29:10 - перейти к сообщению
хм интересненько
во первых надо title и sub_titles перенести в отдельную таблицу один к многим street_title(тут рекомендую узнать что есть такое нормализация)
id, street_id, title
тогда сможем джойнить в запросе

по поводу текста
разбиваем текст на слова и ищем каждое слово в street_title
если слов несколько можно заюзать UNION
числа можно сразу отбросить еще в пыхе чтоб зря не нагружать запрос
пример "улица Чапаева 14"
CODE (SQL):
скопировать код в буфер обмена
  1. (SELECT street_id FROM street_title WHERE title = 'улица'
  2. UNION
  3. SELECT street_id FROM street_title WHERE title = 'Чапаева')
  4. -- 14 отбросим еще в пыхе
  5. LIMIT 1

или
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT * FROM streets
  2. JOIN street_title USING(street_id)
  3. WHERE street_title.title IN ('улица', 'Чапаева')
  4. LIMIT 1
я бы 2 выбрал
както так примерно
(Добавление)
если в streets нет других данных кроме приведенных можно просто привести ее к виду street_title но тут надо учесть что могут появится другие данные в будущем
например население улицы, пешеходная она или транспортная итд
тогда лучше разделить на 2 как выше предлагал
надеюсь понятно тут много буков написал))
3. Serpanok - 10 Октября, 2017 - 15:44:00 - перейти к сообщению
LIME пишет:
хм интересненько
во первых надо title и sub_titles перенести в отдельную таблицу один к многим street_title(тут рекомендую узнать что есть такое нормализация)
id, street_id, title
тогда сможем джойнить в запросе

по поводу текста
разбиваем текст на слова и ищем каждое слово в sub_titles
если слов несколько можно заюзать UNION
числа можно сразу отбросить еще в пыхе чтоб зря не нагружать запрос
пример "улица Чапаева 14"


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

По поводу запроса в принципе мне понятно. А будет ли это эффективно если человек не допишет до конца название улицы? Например "Чапа", ведь у нас строгое сравнение.
Я так понимаю нужно использовать REGEXP. Как во второй запрос его добавить?

Огромное спасибо за ваш совет. Очень помогли! "Спасибо!" уже улетело)
4. LIME - 10 Октября, 2017 - 15:49:13 - перейти к сообщению
Serpanok пишет:
Я так понимаю нужно использовать REGEXP
можно
но тогда отпадает индексация
вариант использовать префиксный LIKE
CODE (SQL):
скопировать код в буфер обмена
  1. WHERE street_title.title LIKE 'улица%' OR street_title.title LIKE 'Чапаева%'

тогда получится
CODE (SQL):
скопировать код в буфер обмена
  1. WHERE street_title.title LIKE 'Чапа%'

просто для каждого слова формируешь свой LIKE и конкатенируешь через OR
тогда индекс будет работать
(Добавление)
но тогда LIMIT надо убрать ибо их может быть много
автокомплит?
5. Serpanok - 10 Октября, 2017 - 15:55:10 - перейти к сообщению
LIME, спасибо огромное!

И тогда получается из этого результата уже ищем по таблице с номерами домов(locations/там я тоже уберу sub_titles) нужный нам номер дома если имеется и его выдаём как нужный результат(первым в списке "советов" пользователю).
6. LIME - 10 Октября, 2017 - 15:56:57 - перейти к сообщению
а если по хорошему я бы заюзал поисковый движек
проще всего elastic search
тогда никаких проблем ни со словами ни с неполным словом и даже морфология работает(чапаев, чапаеву, недочапаев) все найдет
я так делаю в своих проектах но возможно для тебя это будет оверхед
скорее будет оверхед но знай что такое есть
(Добавление)
Serpanok пишет:
первым в списке "советов" пользователю
можно и первый если у нас нет неполного слова
а если слово например "улица Красного" чегото там? первое попавшееся отдашь?
погугли автокомплит
jqueryui autocomplit обычно юзают
дешево и сердито
ajax можно прикрутить
(Добавление)
Serpanok пишет:
И тогда получается из этого результата уже ищем по таблице с номерами домов
можно еще одним джойном добавить
думал догадаешься
7. Serpanok - 10 Октября, 2017 - 16:00:43 - перейти к сообщению
LIME, кстати интересная идея. Пойду читать за него. Время позволяет, да и в будущем пригодится 100%.

Ещё раз спасибо за помощь! Всего хорошего!

 

Powered by ExBB FM 1.0 RC1