2017-05-08 16 views
1

選擇行我有一個像下面3個表:MySQL的:從連接表,其中「中」和「不是」標準用於

表媒體:

+------------------------+ 
| media_id | media_name | 
+------------------------+ 
| 1  | item1  | 
| 2  | item2  | 
| 3  | item3  | 
+------------------------+ 

加入表mediatag:

+--------------------+ 
| media_id | tag_id | 
+--------------------+ 
| 1  | 1  | 
| 1  | 2  | 
| 2  | 1  | 
| 3  | 1  | 
| 3  | 3  | 
+--------------------+ 

表標籤:

+--------------------+ 
| tag_id | tag_name | 
+--------------------+ 
| 1  | blue  | 
| 2  | red  | 
| 3  | white  | 
| 4  | green  | 
+--------------------+ 

我希望檢索具有「藍色」和「白色」標籤但沒有帶「紅色」標籤的媒體的所有媒體。

所以在我的例子,其結果必然是:ITEM2項目3

我嘗試這個查詢,但顯然會顯示物品1:

SELECT m.media_id, media_name FROM media AS m 
INNER JOIN mediatag AS mag ON m.media_id = mag.media_id 
WHERE tag_id = '1' OR tag_id = '3' AND tag_id !='2'; 

如何做到這一點?

具有條件

回答

2

組數據,並僅選擇那些組你提到

SELECT m.media_id, m.media_name 
FROM media AS m 
INNER JOIN mediatag AS mag ON m.media_id = mag.media_id 
GROUP BY m.media_id, m.media_name 
HAVING sum(tag_id in (1,3)) > 0 
    AND sum(tag_id = 2) = 0 
+0

確定嗎? 它似乎只檢索** item3 **,因爲item2不匹配'white'標籤。 – mytom

+0

這不是你想要的嗎?它應該工作 –

+1

@juergend我認爲他們想要藍色或白色標籤沒有紅色。看起來像你可以改變這樣的演示查詢 - http://rextester.com/NRGGU92783 – ollie

0

我會做一個左外連接上選擇的媒體子匹配要排除的行,然後在wheremedia_id IS NULL

SELECT * 
FROM media AS a 
INNER JOIN mediatag AS b ON a.media_id = b.media_id 
INNER JOIN tag c ON b.tag_id = c.tag_id AND c.tag_name = 'blue' 
LEFT OUTER JOIN (
    SELECT a.media_id 
    FROM media AS a 
    INNER JOIN mediatag AS b ON a.media_id = b.media_id 
    INNER JOIN tag c ON b.tag_id = c.tag_id AND c.tag_name = 'red' 
) d ON a.media_id = d.media_id 
WHERE d.media_id IS NULL; 
1

從你期望的結果,好像你希望這樣的實際上是藍色OR白色無紅。您可以使用類似的邏輯,但將其更改爲使用OR:

SELECT m.media_id, m.media_name 
FROM media AS m 
INNER JOIN mediatag AS mt 
    ON m.media_id = mt.media_id 
GROUP BY m.media_id, m.media_name 
HAVING (sum(mt.tag_id = 1) > 0 OR sum(mt.tag_id = 3) > 0) 
    AND sum(mt.tag_id = 2) = 0; 

看到這個demo

如果你不想使用條件邏輯的HAVING子句中,你也可以這樣寫一個NOT EXISTS查詢,並得到同樣的結果:

SELECT DISTINCT m.media_id, m.media_name 
FROM media AS m 
INNER JOIN mediatag AS mt 
    ON m.media_id = mt.media_id 
WHERE mt.tag_id in (1, 3) 
    and not exists (SELECT 1 
        FROM mediatag mt2 
        WHERE m.media_id = mt2.media_id 
         and mt2.tag_id = 2); 

見另一demo

+0

謝謝!我會嘗試這些解決方案。 性能差異? – mytom