2013-10-09 49 views
2

這已經以不同的方式提出過,但我似乎無法得到一些適合我需要的東西。MySQL查詢顯示基於多個過濾器/標籤的結果

這裏的目標是使基於被選擇的標籤返回圖片搜索查詢。可以同時將多個標籤應用於過濾器,這需要使查詢只返回所有選中標籤的照片。想想任何主要的網絡商店,你在進行基本關鍵字搜索後縮小搜索結果。

表1:照片 ID |標題|描述|網址|創建

表2:PhotosTagsXref ID | PHOTOID |標籤識別

表3:PhotosTags ID |標題|分類

我有什麼:

SELECT p.* FROM `PhotosTagsXref` AS pt 
LEFT JOIN `Photos` AS p ON p.`ID` = pt.`PhotoId` 
LEFT JOIN `PhotosTags` AS t ON pt.`TagId` = t.`ID` 
WHERE p.`Description` LIKE "%test%" AND 
???? 
GROUP BY p.`ID` 
ORDER BY p.`Created` DESC LIMIT 20 

的????是我嘗試了一堆東西的地方,但難倒了。問題是我可以輕鬆找到包含帶有一個標籤或另一個標籤的照片的結果集,但是如果應用2,3或4個標籤,我們只需要返回具有數據庫中所有標籤條目的照片。我認爲這將涉及結果集合,但不是100%肯定。

例: 照片1個標籤:藍,白,紅 照片2個標籤:藍色

搜索與「藍色」標籤中的照片返回兩張照片,搜索與標籤照片「藍」和'白色'只返回照片1.

+0

也許CONTAINS條款會幫助你。的 – Tony

+0

可能重複[MySQL的在運營商必須將所有值匹配?(http://stackoverflow.com/questions/7505045/mysql-in-operator-must-match-all-values) –

+0

我會使用內部聯接到子選擇聲明。你如何構建這個查詢,你如何接受投入?如果標籤數量存在上限,那麼您可以在此處執行僅限SQL語句。如果您對標籤沒有限制,那麼您需要在構建sql語句的過程中更具動態性。 – Twelfth

回答

0

不可否認有點難看。但假設PhotosTags.Category具有'藍色','白色'等,請嘗試沿着這條線。

SELECT p.* 
From `Photos` AS p 
WHERE p.`Description` LIKE "%test%" AND 
    AND Exists 
     (Select 1 FROM `PhotosTagsXref` AS pt 
     Inner JOIN `PhotosTags` AS t ON pt.`TagId` = t.`ID` 
     Where pt.`PhotoId` = p.`ID` 
      And t.Category = 'FirstCatToSearch' 
    ) 
    AND Exists 
     (Select 1 FROM `PhotosTagsXref` AS pt 
     Inner JOIN `PhotosTags` AS t ON pt.`TagId` = t.`ID` 
     Where pt.`PhotoId` = p.`ID` 
      And t.Category = 'SecondCatToSearch' 
    ) 
    AND Exists 
     (... 
    ) 
     ... 
+0

,也許不像你說的那麼漂亮,但它很有效。速度似乎也不正常。 –

0
SELECT p.* FROM `PhotosTagsXref` AS pt 
LEFT JOIN `Photos` AS p ON p.`ID` = pt.`PhotoId` 
LEFT JOIN `PhotosTags` AS t ON pt.`TagId` = t.`ID` 
inner join (select PhotoId from PhotosTagsXref 
      LEFT JOIN `PhotosTags` AS t 
      ON pt.`TagId` = t.`ID` 
      where (t.title = 'cond 1' or t.title = 'cond 2' ...) 
      --where t.title in (list condition) **this works as well** 
      having count(1) = (count of conditions)) filter 
    on filter.photoID = pt.PhotoID 
WHERE p.`Description` LIKE "%test%" 
GROUP BY p.`ID` 
ORDER BY p.`Created` DESC LIMIT 20 

這應該工作,我做了使用哪些字段用於過濾一些假設,並加入,您可能需要重新裝備...內部聯接充當過濾器,並應拉出只記錄其中匹配數量等於提交的匹配總數。現在你只需要一種語言來插入這些條件和條件計數值。

+0

這也可能工作,但我無法正確適應,也許是我的錯,但另一個解決方案爲我做了竅門。 –

+0

只是一個警告...... MYSQL有一些已知的性能問題與子選擇。這裏存在的用法確實對其進行了優化,但如果您開始在MySQL查詢中遇到性能問題,那麼一系列if exists語句就是可能的罪魁禍首。幾個鏈接... http://www.mysqldbahelp.com/2010/03/subselect-vs-join-performanace.html#!/2010/03/subselect-vs-join-performanace.html http:// stackoverflow。 com/questions/16403860/mysql-in-clause-using-sub-select-versus-list-of-values – Twelfth

+0

性能可能是一個問題,所以我一定會考慮這個問題,連接通常是我的偏好以及我出於某種原因無法將我的頭圍繞在這個之上。 –

1

假設指定的一組標籤是(redblue),你可以這樣做:

SELECT * FROM `Photos` 
WHERE `Description` LIKE "%test%" 
AND `ID` IN (
    SELECT pt.`PhotoId` FROM `PhotosTagsXref` AS pt 
    JOIN `PhotosTags` AS t ON pt.`TagId` = t.`ID` 
    WHERE t.Title in ('red','blue') /* your set here */ 
    GROUP BY pt.`PhotoId` HAVING COUNT(DISTINCT t.`TagId`)=2 /* # of tags */ 
) 
ORDER BY `Created` DESC LIMIT 20 

顯然,標籤集需要動態創建,以及其計數。

注意:我正在統計DISTINCTTagID因爲我不知道你的表的約束。如果PhotosTagsXRef有一個PK/UNIQUE(PhotoIdTagId)和PhotosTags有一個PK/UNIQUE(TagId),然後COUNT(*)就足夠了。

+0

謝謝。爲我工作! – VGranin