2010-08-10 17 views
6

Jak mogę porównać grupę tagów z tagami innego wpisu w mojej bazie danych, aby uzyskać powiązane posty?Porównaj grupę tagów, aby znaleźć podobieństwo/wynik z PHP/MySQL

Co próbuję zrobić, to porównać grupę tagów w poście do tagów innego wpisu:, ale nie każdego tagu pojedynczo. Powiedzmy, że chcesz uzyskać naprawdę powiązane elementy na podstawie tagów z posta, a następnie pokazać je od najbardziej pokrewnego do najmniej spokrewnionego. Za każdym razem muszą być wyświetlane trzy powiązane pozycje, bez względu na poziom związku.

post A ma tagi: "architektura", "drewno", "nowoczesny", "Szwajcaria"
post B ma tagi: "architektura", "drewno", "nowoczesny"
postu C ma znaczniki: "architektura", "nowoczesny", "kamień"
Post D ma tagi: "architektura", "dom", "rezydencja"

Post B dotyczy stanowiska A o 75% (3 powiązane tagi)
Post C jest powiązany z postem A o 50% (2 powiązane tagi)
Post D dotyczy posta A o 25% (1 powiązany tag)

Jak mogę to zrobić? Obecnie używam 3-tabel.

posts 
> id 
> image 
> date 

post_tags 
> post_id 
> tag_id 

tags 
> id 
> name 

Przeszukałem Internet i przepełnienie stosu, aby dowiedzieć się, jak to zrobić. Moje najbliższe znalezisko to How to find "related items" in PHP, ale w rzeczywistości niewiele mi to rozwiązało.

+0

Jakie jest twoje pytanie? – JochenJung

+0

Zaktualizowałem swój wpis, uzyskując wyraźniejsze pytanie. – stwhite

+0

Jak obliczyć procent? Jakiego związku oczekujesz od relacji A do B (w przeciwieństwie do B do A)? 100% lub 75%? Jeśli odpowiedź wynosi 75%, czy dodanie innego niepowiązanego znacznika do B zmieni to? A co z relacją B do C? 66% lub 50% (2 powiązane, 2 niepowiązane)? –

Odpowiedz

2

UWAGA: To rozwiązanie jest tylko MySQL, jak MySQL ma swoją własną interpretację GROUP BY

używałem również własną kalkulację podobieństwa. Wziąłem liczbę identycznych tagów i podzieliłem ją przez średnią liczbę tagów w poście A i B B. Więc jeśli post A ma 4 tagi, a post B ma 2 tagi, które są wspólne z A, podobieństwo wynosi 66% .

(SHARED:2/((A:4 + B:2)/2) lub (SHARED:2)/(AVG:3)

To powinno być łatwe do zmiany formuły, jeśli chcesz/potrzeby ...

SELECT 
sourcePost.id, 
targetPost.id, 

/* COUNT NUMBER OF IDENTICAL TAGS */ 
/* REF GROUPING OF sourcePost.id and targetPost.id BELOW */ 
COUNT(targetPost.id)/
(
    (
    /* TOTAL TAGS IN SOURCE POST */ 
    (SELECT COUNT(*) FROM post_tags WHERE post_id = sourcePost.id) 

    + 

    /* TOTAL TAGS IN TARGET POST */ 
    (SELECT COUNT(*) FROM post_tags WHERE post_id = targetPost.id) 

)/2 /* AVERAGE TAGS IN SOURCE + TARGET */ 
) as similarity 
FROM 
posts sourcePost 
LEFT JOIN 
post_tags sourcePostTags ON (sourcePost.id = sourcePostTags.post_id) 
INNER JOIN 
post_tags targetPostTags ON (sourcePostTags.tag_id = targetPostTags.tag_id 
          AND 
           sourcePostTags.post_id != targetPostTags.post_id) 
LEFT JOIN 
posts targetPost ON (targetPostTags.post_id = targetPost.id) 
GROUP BY 
sourcePost.id, targetPost.id 
+0

Ivar, naprawdę doceniam twoją pomoc - działa to bardzo ładnie.Zmieniłem nieznacznie grupę, aby bardziej uporządkować wyniki. Jedyną rzeczą, którą się zastanawiam, jest to, że jeśli jest tak, że jeśli są mniej niż 3 wyniki, uzyskać losowy zestaw elementów z bazy danych? – stwhite

+0

Jakieś rozwiązanie dla PostgreSql? – takeshin

0

umieścić znaczniki do tablicy. Każda tablica jest odpowiednio nazwana Post A/Post B itd. Następnie użyj array_diff_assoc(), aby dowiedzieć się, jak różne są tablice.

Ale tak naprawdę, rozwiązanie Ivars będzie działało lepiej, jednak jest to łatwiejsze do zrozumienia :)

+0

Jest to zdecydowanie łatwiejsze do zrozumienia i jest moim rozwiązaniem awaryjnym, jeśli muszę. Próbuję teraz sprawdzić, czy w przypadku mniej niż 3 wyników zwróconych, czy istnieje sposób (w zapytaniu), aby uzyskać losowy zestaw elementów z bazy danych? – stwhite

Powiązane problemy