2010-09-15 48 views
1

基于How to implement tagging system similar to SO in php/mysql?MySQL的许多一对多的标签实现+完整的标签上市

香港专业教育学院取得的微小变化,并具有以下图片广告代码:

SELECT I.imageId, GROUP_CONCAT(DISTINCT T.tagName SEPARATOR ' '), COUNT(*)
FROM Images I
INNER JOIN ImageTagMap M ON I.imageId = M.imageId
INNER JOIN ImageTags T ON T.tagId = M.tagId
WHERE T.tagName LIKE '%new%' OR T.tagName LIKE '%yo%'
GROUP BY I.imageId
ORDER BY COUNT(*) DESC

目前,这个成功获取了所有那些完整填写WHERE子句的图像的imageId,并根据最高命中次数(不包含由GROUP BY子句生成的命中)对它们进行排序。它也获得所有匹配的标签名称并将它们粘在一个字符串中。不错。

我真的很想为用户,是有相关图片的所有tagNames。目前,返回的tagNames只是与LIKE语句匹配的那些。例如如果图片被标记为“2010纽约”,并且我搜索(如上)“新哟”,它将返回imageId,“纽约”。但我想要匹配图片的所有标签信息,我想imageId,“纽约2010”。

一个简单的解决方案是将上述查询粘贴到子查询中,然后使用imageId IN的新WHERE子句(以上查询为子查询)重新运行连接。虽然这看起来很愚蠢(即使优化器可能会用它做魔术),当然,我不需要重新运行两次完全相同的连接?或者我呢?

另一方面,是否有更好的方法来搜索标签,而不是LIKE的一堆卡住?

回答

1

SELECT
M.imageId,
GROUP_CONCAT(DISTINCT T2.tagName SEPARATOR ' ') AS tagNames,
COUNT(DISTINCT T.tagName) AS relevance
FROM ImageTagMap M
JOIN ImageTags T ON T.tagId=M.tagId
JOIN ImageTagMap M2 ON M2.imageId=M.imageId
JOIN ImageTags T2 ON T2.tagId=M2.tagId
WHERE T.tagName LIKE '%new%' or T.tagName LIKE '%yo%'
GROUP BY M.imageId
ORDER BY relevance DESC

必须重新加入两次。任何简短的方式都是受欢迎

0

添加另一个JOIN使用的ImageTags表,并就代替你对测试标签一个CONCAT:

SELECT 
    M.imageId, 
    GROUP_CONCAT(DISTINCT Ta.tagName SEPARATOR ' ') AS tagNames, 
    COUNT(DISTINCT Tc.tagName) AS relevance 
FROM ImageTagMap M 
JOIN ImageTags Tc ON Tc.tagId=M.tagId 
JOIN ImageTags Ta ON Ta.tagId=M.tagId 
WHERE Tc.tagName LIKE '%new%' OR Tc.tagName LIKE '%yo%' 
GROUP BY M.imageId 
ORDER BY relevance DESC 

(我摆脱了加盟Images因为你没有出现)

有没有更好的方式来搜索标签,而不是LIKE的一堆卡住?

如果你真的必须对标签进行任意子字符串匹配然后否,那么就没有可转位的方法来做到这一点。考虑到合适的索引,平等测试或固定左手部分LIKE(即LIKE 'new yo%')将更加高效。

+0

添加另一个连接的想法很好,但它对我无效。我需要重新加入两次才能工作。生病发布在下面,如果你有一个更短的方式做到这一点,让我知道 – davin 2010-09-15 17:28:23

+0

你是绝对正确的 - + 1的答案。 ImageTagMap上的自连接是必要的,否则自然'Tc.tagId'必须'= Ta.tagId'。我应该注意到了! – bobince 2010-09-15 17:49:01