2010-01-04 90 views
6

我有一個將圖像與標籤匹配的Web應用程序,我需要創建一種動態優化標籤搜索結果的方式。但是,我無法找到一個乾淨的方式來進行SQL查詢,而這正是我需要您的幫助的地方。SQL n對n匹配多個值

這個想法是,如果我搜索標籤「乾淨」和「狗」,我將有圖像結果,同時具有標籤「乾淨」和「狗」。如果我還包含「小」標籤,我的結果將不得不縮小到具有三個標籤關聯的圖像。

因此,有一個N對N的關係,這是做到這一點的正確方法?

我自然的方法是生成代碼這樣的事情,但我肯定不喜歡往哪裏去:

SELECT images.* 
FROM images 
INNER JOIN image_tags ON ... 
INNER JOIN tags ON ... 
WHERE tags.tag = @tag1 
AND EXISTS 
(
    SELECT 1 
    FROM images 
    INNER JOIN image_tags ON ... 
    INNER JOIN tags ON ... 
    WHERE tag = @tag2 
    AND EXISTS 
    (
    SELECT 1 
    FROM images 
    INNER JOIN image_tags ON ... 
    INNER JOIN tags ON ... 
    WHERE tag = @tag3 
    AND EXISTS (...) 
    ... 
) 
) 

當然,這不是真的很好。任何想法?

謝謝!

回答

7

類似的東西可以工作(我用idSELECTGROUP BY,使用你所需要的列。

SELECT images.id 
FROM images 
INNER JOIN image_tags ON ... 
INNER JOIN tags ON ... 
WHERE tags.tag IN (@tag1, @tag2, @tag3) 
GROUP BY images.id 
HAVING COUNT(*) = @number_of_tags 

如果你有3個標籤,如在你的榜樣,然後number_of_tags必須是3,加入將導致3行每id匹配。

您可以動態地創建查詢,或者,比如說定義它,10個標籤,並不會在標籤出現的值初始化。

+0

這對於允許/需要的標籤數量非常嚴格,並且對每個指定的標籤而不是每個圖像都返回一行。 – 2010-01-04 17:02:05

+0

'GROUP BY'應該避免爲每個標籤返回一行。我編輯了這個問題,以顯示它如何與動態數量的標籤一起工作。 – 2010-01-04 17:17:45

+0

非常感謝!我沒有想過用HAVING COUNT()重新檢查結果。 – Alpha 2010-01-05 14:11:56

0

我不會使用N-N關係,而是使用文本字段來存儲標籤。

這聽起來很骯髒,因爲我們失去了常態,但標籤通常只用於文本搜索,而且磁盤空間很便宜。

然後,您可以運行

SELECT * FROM images WHERE tags LIKE '%clean%' AND tags LIKE '%dog%'... 
+0

@Peter - 尼斯字母排序... d在c後面出現... ;-) – 2010-01-04 16:52:33

+0

注意:您的解決方案會爲每個標籤計數圖像,重命名或刪除標籤更復雜。 – 2010-01-04 16:53:43

+0

@ md5sum:OMG!對不起,我不得不刪除那個帖子;-) – 2010-01-04 16:54:35

0

使用相交,你可以這樣做:

SELECT images.* 
FROM images 
WHERE image_id IN 
    (
    SELECT image_id FROM image_tags WHERE tag_id = 
     (SELECT tag_id FROM tags WHERE tag = @tag1) 
    INTERSECT 
    SELECT image_id FROM image_tags WHERE tag_id = 
     (SELECT tag_id FROM tags WHERE tag = @tag2) 
    INTERSECT 
     .... 
    ) 

這將選擇基於交點(匹配所有)在image_tags標籤的所有圖像。