2010-09-24 9 views
7

Próbuję dowiedzieć się, jak zamówić elementy z pasującymi tagami przez liczbę pasujących tagów.Zamawianie elementów z pasującymi tagami według liczby tagów pasujących do

Powiedzmy masz trzy MySQL tabele:

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

Teraz powiedzmy masz cztery artykuły gdzie:

article_id = 1 ma tagów " humor, "" f unny "i" zabawny ".

article_id = 2 ma tagi "zabawny", "głupi" i "głupkowaty".

article_id = 3 ma tagi "zabawny", "głupi" i "głupkowaty".

article_id = 4 ma tag "całkowicie poważne".

Musisz znaleźć wszystkie artykuły związane z article_id = 2 według co najmniej jednego pasującego tagu i zwrócić wyniki w kolejności najlepiej pasujących. Innymi słowy, article_id = 3 powinno być na pierwszym miejscu, z article_id = 1 sekundą, a article_id = 4 nie powinno się w ogóle pokazywać.

Czy jest to coś, co można zrobić w zapytaniach SQL lub samodzielnie, czy jest to lepsze rozwiązanie dla czegoś takiego jak Sphinx? Jeśli jest to pierwsze, jakiego rodzaju zapytanie powinno zostać wykonane i jaki rodzaj indeksów powinien zostać stworzony dla najbardziej wydajnych wyników? Jeśli to drugie, proszę rozwiń.

Odpowiedz

10

spróbować czegoś takiego:

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; 

Składnia może potrzebować trochę szczypanie dla MySQL.

lub ten, który faktycznie działa: ;-)

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; 
+0

Druga składnia jest fantastyczna i działa dokładnie tak, jak potrzebowałem. Dzięki wielkie! –

2

coś w rodzaju:

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 

tylko z typowych indeksów, zakładając articles_tags ma PK (id_artykulu, tag_id) oraz index na tags.title