|
|
|
| Мы задаём одно или несколько ключевых слова для поиска (в форме одним ключевым словом считаестся всё, что на одной строке, т. е. ключевым словом может стать даже предложение, например «День святого Валентина»).
Бд ищет все файлы (в бд файлы определены своими названиями и идентификаторами), к которым привязаны сразу все наши заданные слова.
Бд проверяет у всех найденных файлов связи с другими словами и выдаёт все связанные слова, отсортированные по частоте встречания с нашими заданными словами в этих файлах.
Имеются три таблицы:
tablizca_izobrazhenij (id, izobrazheniya) — айди и имя файла;
tablizca_slov (id, slova) — айди и слово;
tablizca_svyazej (id_izobrazheniya, id_slova).
Помогите, пожалуйста, составить SQL запрос.
Вот что получилось у меня (связка с PHP), но он ищет все файлы, к которым привязано хоть одно заданное слово, а нужно, чтоб искал только те файлы, к которым привязаны сразу все слова:
//############################################
Форма и PHP код:
<form method="post" action="index_2.php">
<textarea name="vvod_slov" wrap="off" class="vvod_slov" placeholder="" autofocus></textarea>
<div class="zamechaniya">Разделяйте значимые слова переносом строки.</div>
<hr class="otbivka_12">
<input name="podobrat" type="submit" class="knopka" value="Подобрать">
<hr class="otbivka_48">
<div class="sbros"><a href="index.php">Сбросить и сначала</a></div>
</form>
$vvod_slov = $_POST["vvod_slov"]; //помещаем в переменную опорные слова строкой
$oporn_slova = explode("\n", $vvod_slov);//разбиваем строку опорных слов на части и заносим их в массив(есть лишние пробелы)
for ($i = 0; $i < count($oporn_slova); $i++)//перебираем массив из строки в новый массив (без лишних пробелов)
{
$oporn_slova_bez_probelov[$i] = trim($oporn_slova[$i]);
}
$otmetka_ptichkoj = count($oporn_slova_bez_probelov);//сколько первых слов (первыми пойдут те, которые ввёл пользователь) отметить птичкой
$osnova_stroki_zaprosa = implode("', '", $oporn_slova_bez_probelov);//делаем из массива опорных слов основу строки для sql запроса
$stroka_zaprosa = "'" . $osnova_stroki_zaprosa . "'";//окончательно формируем строку для sql запроса
$rezultat_podbora = mysql_query//подставляем строку для sql запроса в полный запрос
("
SELECT `slova` FROM `tablizca_slov` WHERE `id` in
(SELECT `id_slova` FROM `tablizca_svyazej` WHERE `id_izobrazheniya` in
(SELECT `id_izobrazheniya` FROM `tablizca_svyazej` WHERE `id_slova` in
(SELECT `id` FROM `tablizca_slov` WHERE `slova` IN (" . $stroka_zaprosa . "))))
");
//############################################
Пожалуйста, прокомментируйте свой запрос, чтоб я мог его логику проследить, т. к. у меня только зачаточные знания синтаксиса.
И скажите, какую тему по БД изучить в первую очередь, чтобы справляться с такими запросами. | |
|
|
|
|
|
|
|
для: Андрей К.
(19.07.2014 в 11:41)
| | 1. Будет весьма неплохо если вы выложите кусочек дампа базы, тестовый запрос и желаемый результат.
2. Использовал свои имена таблиц, потому что tablizca_izobrazhenij - это мрак =)
"SELECT path as image_path
FROM images i
WHERE i.id IN (
SELECT wi.image_id
FROM words_to_images wi
JOIN words w ON w.id = wi.word_id
WHERE w.word IN ($query)
GROUP BY wi.image_id
HAVING COUNT(wi.image_id) = $words_count
)"
|
Набросал запрос, который вряд ли сразу заработает (если сделаете первый пункт - будет возможность его доработать). Суть запроса такова - при выборке из таблицы связей (words_to_images) считаем кол-во совпадений по словам используя группировку по wi.image_id и отбрасываем результаты, если кол-во совпадений меньше кол-ва слов из введенного пользователем запроса.
3. Вы говорили про "сортировку по частоте встречания", но в вашем запросе про это ни слова.
4.
<?
for ($i = 0; $i < count($oporn_slova); $i++)//перебираем массив из строки в новый массив (без лишних пробелов)
{
$oporn_slova_bez_probelov[$i] = trim($oporn_slova[$i]);
}
|
это все можно заменить на вызов одной функции (см. array_map)
PS оформляйте код в ваших сообщениях в псевдо-теги! | |
|
|
|
|
5.6 Кб |
|
|
для: Igorek
(21.07.2014 в 15:44)
| | Спасибо, что уделили внимание моему вопросу. Я долго не отвечал, потому что были трудности со входом в аккаунт (восстанавливал через переписку с администрацией). За это время обсуждение темы на других форумах помогло с решением.
Вот текущее решение, (Как организовать бд для вот такой задачи?). Я переделал его под свои названия:
Код:
$SQL_zapros = "select ts.s, count(*)
from (
select t_s.id_n
from ts
join t_s on t_s.id_s = ts.ids
where ts.s in ('" . $oporn_slova . "')
group by t_s.id_n having count(/*distinct*/ t_s.id_s) = " . $kolichestvo_opornyx_slov . "
) g
join t_s on t_s.id_n = g.id_n
join ts on ts.ids = t_s.id_s
group by t_s.id_s
order by count(*) desc, ts.s
;
";
|
tn (idn, n) — таблица наборов слов.
ts (ids, s) — таблица слов.
t_s (id_n, id_s) — таблица связей между наборами и словами.
Дамп бд прилагаю.
Буду рад комментариям, если такие появятся. | |
|
|
|