Упорядочение элементов с соответствующими тегами по количеству соответствующих тегов - PullRequest
9 голосов
/ 24 сентября 2010

Я пытаюсь выяснить, как упорядочить элементы с совпадающими тегами по количеству совпадающих тегов.

Допустим, у вас есть три таблицы MySQL:

  • tags(tag_id, title)
  • articles(article_id, some_text)
  • articles_tags(tag_id, article_id)

Теперь предположим, что у вас есть четыре статьи, где:

article_id = 1 имеет теги "юмор", "" забавно "и" смешно ".

article_id = 2 имеет теги" забавный "," глупый "и" тупой ".

article_id = 3 имеет теги" забавный "«глупый» и «тупой».

article_id = 4 имеет тег «совершенно серьезно».

Вам нужно найти все статьи, связанные с article_id = 2, по крайней мере одним подходящим тегом,и вернуть результаты в порядке лучших матчей.Другими словами, article_id = 3 должен стоять первым, а article_id = 1 - вторым, а article_id = 4 не должен отображаться вообще.

Это то, что выполнимо в SQL-запросах или в одиночку, или это лучше подходитза что-то вроде сфинкса?Если первое, какой тип запроса должен быть выполнен и какие индексы должны быть созданы для наиболее производительных результатов?Если последнее, пожалуйста, расширьте.

Ответы [ 2 ]

11 голосов
/ 24 сентября 2010

Попробуйте что-то вроде этого:

select article_id, count(tag_id) as common_tag_count
from articles_tags 
group by tag_id
where tag_id in (
    select tag_id from articles_tags where article_id = 2
) and article_id != 2
order by common_tag_count desc;

Синтаксис может потребовать небольшой настройки для MySQL.

или тот, который действительно работает:; -)

SELECT at1.article_id, Count(at1.tag_id) AS common_tag_count
FROM articles_tags AS at1 INNER JOIN articles_tags AS at2 ON at1.tag_id = at2.tag_id
WHERE at2.article_id = 2
GROUP BY at1.article_id
HAVING at1.article_id != 2
ORDER BY Count(at1.tag_id) DESC;
2 голосов
/ 24 сентября 2010

Что-то похожее:

SELECT a.* 
FROM articles AS a 
INNER JOIN articles_tags AS at ON a.id=at.article_id
INNER JOIN tags AS t ON at.tag_id = t.id
WHERE t.title = 'funny' OR t.title = 'goofy' OR t.title = 'silly' AND a.id != <article_id>
GROUP BY a.id
ORDER BY COUNT(a.id) DESC

Имея только обычные индексы, при условии что article_tags имеет PK (article_id, tag_id) и индекс для tags.title

...