Ajudaria se você nos mostrasse suas estruturas de tabela, para que eu possa ser mais específico.
Estou supondo que você tenha uma estrutura semelhante a esta:
Table item: (id, itemname)
1 item1
2 item2
3 item3
4 item4
5 item5
Table tag: (id, tagname)
1 cool
2 red
3 car
Table itemtag: (id, itemid, tagid)
1 1 2 (=item1, red)
2 2 1 (=item2, cool)
3 2 3 (=item2, car)
4 3 1 (=item3, cool)
5 3 2 (=item3, red)
6 3 3 (=item3, car)
7 4 3 (=item3, car)
8 5 3 (=item3, car)
Em geral, minha abordagem seria começar contando cada tag separada.
-- make a list of how often a tag was used:
select tagid, count(*) as `tagscore` from itemtag group by tagid
Isso mostra uma linha para cada tag que foi atribuída ao item, com uma pontuação.
No nosso exemplo, isso seria:
tag tagscore
1 2 (cool, 2x)
2 2 (red, 2x)
3 4 (car, 4x)
set @ItemOfInterest=2;
select
itemname,
sum(tagscore) as `totaltagscore`,
GROUP_CONCAT(tags) as `tags`
from
itemtag
join item on itemtag.itemid=item.id
join
/* join the query from above (scores per tag) */
(select tagid, count(*) as `tagscore` from itemtag group by tagid ) as `TagScores`
on `TagScores`.tagid=itemtag.tagid
where
itemid<>@ItemOfInterest and
/* get the taglist of the current item */
tagid in (select distinct tagid from itemtag where [email protected])
group by
itemid
order by
2 desc
Explicação:A consulta possui 2 subconsultas:Uma é obter as tags de lista do item de interesse. Queremos trabalhar apenas com eles. A outra subconsulta gera uma lista de pontuações por tag.
Assim, no final, cada item no banco de dados tem uma lista de pontuações de tags. Essas pontuações são somadas com
sum(tagscore)
, e esse número é usado para ordenar o resultado (pontuações mais altas no topo). Para mostrar uma lista de tags disponíveis, usei GROUP_CONCAT.
A consulta resultará em algo assim (criei os dados reais aqui):
Item TagsScore Tags
item3 15 red,cool,car
item4 7 red,car
item5 7 red
item1 5 car
item6 5 car