|
|
|
| Есть таблица, в виде: | ID | Слово |
ID - идентификатор человека, слово - любое варчар слово.
Суть - каждый юзер сайта описывает свой характер 1 словом, таких описаний у каждого юзера много. Тоесть в таблице может быть много записей с разными словами, прочее...
Цель - другой пользователь ищет текущего путем вписывания 6 ключевых слов. Нужно чтобы достался из бд юзер, у которого максимальное число совпадений с этими поисковыми словами.
Предпологаю, что нужно использовать GROUP BY по ID, но как ранжировать по максимальному количеству совпадений???
Группируя, мы получим множество слов которое принадлежит конкретному человеку - но как быть дальше... | |
|
|
|
|
|
|
|
для: nikolayers
(23.07.2013 в 05:37)
| | Рабочий пример:
В бд записи
id | word
-----------
1 | Злой
1 | Сердитый
1 | Наглый
2 | Агрессивный
2 | Злой
-----------------
В поиске пишется ЗЛОЙ СЕРДИТЫЙ Белый зеленый красный .... и должно вернуть через селект юзера с id1 так как там макс. число совпадений | |
|
|
|
|
|
|
|
для: nikolayers
(23.07.2013 в 05:43)
| |
SELECT id
FROM tbl
WHERE word IN('ЗЛОЙ','СЕРДИТЫЙ','Белый','зеленый','красный')
GROUP BY id
ORDER BY count(*) DESC
LIMIT 1
|
| |
|
|
|
|
|
|
|
для: Sfinks
(23.07.2013 в 08:55)
| | Спасибо огромное, работает)) | |
|
|
|
|
|
|
|
для: Sfinks
(23.07.2013 в 08:55)
| | Помогите пожалуйста еще...я модифицировал код под свои нужды:
$pat - массив из 6-ти слов
$s - количество введенных слов в поиске
$c - сколько должно минимально совпасть поисковых слов с табличными
Это сделано для того, чтобы пользователи, которые вводят 1 слово, никак не могли достать из базы характеристику например из 6ти слов
SELECT `user` FROM `words`
WHERE `user` IN (SELECT `user`
FROM `words`
WHERE `word` IN ('{$pat[0]}', '{$pat[1]}','{$pat[2]}','{$pat[3]}','{$pat[4]}','{$pat[5]}')
AND `user`!='".$user."'
GROUP BY `user`
HAVING count(*) >= ".$c."
ORDER BY count(*) DESC
)
GROUP BY `user`
HAVING count(*) <= ".++$s."
LIMIT 1
|
Сам код работает, я проверил много вариантов (не исключаю ошибок)...Но мне кажется, что моя реализация - не единственно правильная и совсем не изящная...Возможно ли код сократить или переделать более правильно? | |
|
|
|
|
|
|
|
для: nikolayers
(23.07.2013 в 18:46)
| | А вот так разве не тоже самое получится?
SELECT `user`
FROM `words`
WHERE `word` IN ('{$pat[0]}', '{$pat[1]}','{$pat[2]}','{$pat[3]}','{$pat[4]}','{$pat[5]}')
AND `user`!='".$user."'
GROUP BY `user`
HAVING count(*) >= ".$c."
AND count(*) <= ".++$s."
ORDER BY count(*) DESC
LIMIT 1
|
А почему ++$s, а не просто $s?
Ну и аккуратнее будет так выглядеть:
SELECT `user`, count(*)co
FROM `words`
WHERE `word` IN ('{$pat[0]}', '{$pat[1]}','{$pat[2]}','{$pat[3]}','{$pat[4]}','{$pat[5]}')
AND `user`!='".$user."'
GROUP BY `user`
HAVING co BETWEEN ".$c." AND ".++$s."
ORDER BY co DESC
LIMIT 1
|
| |
|
|
|
|
|
|
|
для: Sfinks
(23.07.2013 в 19:17)
| | помоему разница есть)) в моем случае внутренний селект считает COUNT(*) по совпавшим, а внешний считает ОБЩЕЕ количество всех слов пользователя...возможно ошибаюсь)) но скрипт дает разные результаты для моего и вашего примера | |
|
|
|
|
|
|
|
для: nikolayers
(23.07.2013 в 19:49)
| | Возможно.... Хотя странно.
В любом случае
в подзапросе лишнее и ни на что не влияет.
Хм... не доходит пока до меня почему разные результаты.... Возможно нужно меньше работать =) | |
|
|
|