2017-02-21 154 views
0

我可能會丟失一些明顯的東西,但我需要一個只返回匹配同一列上多個條件的記錄的查詢。SELECT匹配多個WHERE標準(來自鏈接表)

該表格是一個簡單的鏈接表,它將標籤鏈接到照片,即標籤可以應用於多張照片,照片可以有多個標籤。

photoid | tagid 
---------------- 
343 | 2 
343 | 5 
343 | 8 
522 | 5 
522 | 1 
522 | 10 
522 | 8 
118 | 8 
118 | 5 
etc... 

如所看到的PHOTOID 343具有3個標籤。

現在,我需要的是一個查詢,爲我提供具有特定標籤的所有照片的照片。這些照片應具有標籤識別1 標籤識別2,並應具有標籤識別5 標籤識別8,但必須不已經 10 TAGID即 像 (tagid=1 OR tagid=2) AND (tagid=5 AND tagid=8) AND tagid!=10。 在上面的例子中,只有343匹配。

我試圖與WHERE INGROUP BYHAVING COUNT

SELECT PhotoTags.photoid, FROM PhotoTags 
WHERE (PhotoTags.tagid) IN ((5),(8)) AND (PhotoTags.tagid) NOT IN (10) 
GROUP BY PhotoTags.photoid 
HAVING count(distinct PhotoTags.tagid)=2 

此僅做工作的一部分,它給了我匹配標籤識別5和8,但不是所有的10張照片如何添加AND (tagid=1 OR tagid=2)標準到查詢?

+1

如何'tagid'既'5'和'8 '?同樣做'tagid IN(5,8)'意味着'tagID!= 10'。 –

+0

所以,你正在試圖找到所有'* tagid' 5 *和* 8的'photoid's? –

+0

一張照片可能有多個標籤,我試圖查詢具有特定標籤的所有照片。 @火箭:在這個例子中,我希望所有的'photoid'都有'tagid'' [[]]或2,並且[tagital] 5 [_italic_]和8都有[_italic_] tagid' 10. –

回答

0

我不知道這是否是最好解決方案,但它似乎工作。您可以使用GROUP_CONCAT來列出所有標籤的圖片,然後您可以使用HAVING根據該值進行過濾。

SELECT photoid, GROUP_CONCAT(tagid ORDER BY tagid ASC) AS tags 
FROM PhotoTags 
GROUP BY photoid DESC 
HAVING tags RLIKE '(^|,)5,.*8(,|$)' 
AND tags NOT RLIKE '(^|,)10(,|$)'; 

您也可以嘗試使用FIND_IN_SET,而不是一個正則表達式(RLIKE):

SELECT photoid, GROUP_CONCAT(tagid ORDER BY tagid ASC) AS tags 
FROM PhotoTags 
GROUP BY photoid DESC 
HAVING FIND_IN_SET(5, tags) AND FIND_IN_SET(8, tags) 
AND NOT FIND_IN_SET(10, tags); 

編輯:如果您要添加的OR條款,試試這個:

SELECT photoid, GROUP_CONCAT(tagid ORDER BY tagid ASC) AS tags 
FROM PhotoTags 
GROUP BY photoid DESC 
HAVING (FIND_IN_SET(1, tags) OR FIND_IN_SET(2, tags)) 
AND FIND_IN_SET(5, tags) AND FIND_IN_SET(8, tags) 
AND NOT FIND_IN_SET(10, tags); 
+0

謝謝,但是這和我原來的查詢做的事情是一樣的,對吧?不知怎的,「AND(tagid = 1 OR tagid = 2)」標準可以添加到您的示例中嗎? *我已更新說明以使其更清晰。* –

+0

不,它不。您的原始查詢實際上並沒有爲多個標籤檢查相同的Photoid。 –

+0

如果您想添加'OR',那麼只需將該子句添加到'HAVING'。 –

0

如果你這樣做

WHERE (PhotoTags.tagid) IN ((5),(8)) AND (PhotoTags.tagid) NOT IN (10) 

這一點,並不會考慮採取,因爲已檢查該標籤識別爲5或8

AND (PhotoTags.tagid) NOT IN (10) 

IN可以做到只有逗號分隔值,請記住,並通過OR優先,嘗試這一點,並檢查它是否給你你想要的結果,這將僅選擇5或8或1或2

SELECT PhotoTags.photoid, FROM PhotoTags 
WHERE (PhotoTags.tagid) IN (5,8,1,2) 
GROUP BY PhotoTags.photoid 
HAVING count(distinct PhotoTags.tagid)=2 
+0

'(PhotoTags.tagid)NOT IN(10)'是有效的SQL。你可以有一個值的列表。 –

+0

建議的查詢,其中'WHERE IN'中的四個值和匹配2的'count'匹配任何具有四個'tagid'中的兩個或更多個的'photoid'。所以這不是我想要的四個。 –

0

好像你想找到的所有照片的標籤識別是:

  • 具有至少標記(1,2)
  • 有一個標籤10
  • 具有標籤的兩個(5,8)

第一個要求可以通過IN子句和SELECT DISTINCT輕鬆處理。

第二個要求可能是最好使用NOT EXISTS處理。

第三個要求可以處理幾種方法:使用子查詢,NOT EXISTSGROUP BY/HAVING,等我將使用子查詢給你一個例子,但是這可能不是您理想的選擇,尤其是在所需標籤的數量並不總是2.

希望這可以讓你開始在正確的道路上,你的作品很好的解決方案:

select distinct t1.photoid 
from PhotoTags t1 
    inner join (
    select distinct photoid 
    from PhotoTags 
    where tagid = 5 
    ) t2 on t2.photoid = t1.photoid 
    inner join (
    select distinct photoid 
    from PhotoTags 
    where tagid = 8 
    ) t3 on t3.photoid = t1.photoid 
where t1.tagid in (1,2) 
    and not exists (
    select NULL 
    from PhotoTags t4 
    where t4.photoid = t1.photoid 
    and t4.tagid = 10 
) 
+0

這正是我想要達到的查詢,很好的解釋! (我必須檢查解決方案是否適用於我)。 –

+0

謝謝,它似乎適用於這個例子。 如果我需要在上面添加一個標準,如: 「有**至少一個**(15,16)」標籤? –

+0

你可以使用'DISTINCT'和'IN'加入一個額外的子查詢,就像這樣:'inner join(從PhotoTags中選擇不同的photoid,其中tagid在(15,16))t5上t5.photoid = t1.photoid' –