2010-09-24 9 views
7

Ich versuche herauszufinden, wie Artikel mit übereinstimmenden Tags nach der Anzahl der übereinstimmenden Tags sortiert werden.Artikel mit übereinstimmenden Tags nach Anzahl der Tags sortieren, die übereinstimmen

Angenommen, Sie haben drei MySQL-Tabellen:

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

Lassen Sie uns jetzt sagen, Sie vier Artikel, wo:

article_id = 1 Tags hat " Humor, "" f unny, "und" urkomisch. "

article_id = 2 hat Tags "lustig", "albern" und "doof".

article_id = 3 hat Tags "lustig", "albern" und "doof".

article_id = 4 hat das Etikett "vollständig ernst."

Sie müssen alle Artikel zu article_id = 2 mit mindestens einem passenden Tag finden und die Ergebnisse in der Reihenfolge der besten Übereinstimmungen zurückgeben. Mit anderen Worten, article_id = 3 sollte zuerst kommen, mit article_id = 1 Sekunde, und article_id = 4 sollte überhaupt nicht angezeigt werden.

Ist das etwas, das in SQL-Abfragen oder alleine machbar ist, oder ist es für etwas wie Sphinx besser geeignet? Wenn erstere, welche Art von Abfrage sollte durchgeführt werden, und welche Art von Indizes sollte für die performantesten Ergebnisse erstellt werden? Wenn letzteres, bitte erweitern Sie.

Antwort

10

versuchen, etwas wie folgt aus:

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; 

Syntax ein wenig Gefummel für MySQL benötigen.

oder diese eine, die tatsächlich funktioniert: ;-)

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

Die zweite Syntax ist fantastisch und funktionierte genau so, wie ich es brauchte. Vielen Dank! –

2

etwas wie:

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 

Mit nur den üblichen Indizes articles_tags hat PK von (article_id, tag_id) unter der Annahme, und ein index auf tags.title