Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Хитрый SQL запрос.
 
 автор: Андрей К.   (19.07.2014 в 11:41)   письмо автору
 
 

Мы задаём одно или несколько ключевых слова для поиска (в форме одним ключевым словом считаестся всё, что на одной строке, т. е. ключевым словом может стать даже предложение, например «День святого Валентина»).
Бд ищет все файлы (в бд файлы определены своими названиями и идентификаторами), к которым привязаны сразу все наши заданные слова.
Бд проверяет у всех найденных файлов связи с другими словами и выдаёт все связанные слова, отсортированные по частоте встречания с нашими заданными словами в этих файлах.

Имеются три таблицы:

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 . "))))
");

//############################################

Пожалуйста, прокомментируйте свой запрос, чтоб я мог его логику проследить, т. к. у меня только зачаточные знания синтаксиса.
И скажите, какую тему по БД изучить в первую очередь, чтобы справляться с такими запросами.

  Ответить  
 
 автор: Igorek   (21.07.2014 в 15:44)   письмо автору
 
   для: Андрей К.   (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 оформляйте код в ваших сообщениях в псевдо-теги!

  Ответить  
 
 автор: Андрей К.   (24.07.2014 в 13:37)   письмо автору
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) — таблица связей между наборами и словами.

Дамп бд прилагаю.
Буду рад комментариям, если такие появятся.

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования