2010-09-15 42 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