2012-12-13 104 views
4

這裏長時間潛伏着,一直在使用這個網站的建議多年,現在我有一個問題,我找不到答案 - 米確定解決方案很簡單,但!PHP MYSQL查詢,使用多個表中的數據搜索多個字段/列

我正在爲音樂曲目建立一個標記系統。我有三個表

曲目

--------------- 
| id | name | 
--------------- 
| 1 | Track1 | 
| 2 | Track2 | 
--------------- 

Taglinks

-------------------------- 
| id | tag_id | track_id | 
-------------------------- 
| 1 | 1  | 1  | 
| 2 | 2  | 1  | 
| 3 | 2  | 2  | 
-------------------------- 

標籤

------------------------- 
| id | tag  | type | 
------------------------- 
| 1 | acoustic | genre | 
| 2 | anger | mood | 
------------------------- 

我想能夠獲得具有例如標籤的音軌的軌道名稱:聲音,類型:流派和標籤:憤怒,類型:心情。所以在這種情況下,我想跟蹤1,因爲這有兩個標籤。

當前查詢我是

SELECT tracks.name 
FROM tracks 
JOIN taglinks ON tracks.id=taglinks.track_id 
JOIN tags ON (tags.type='genre' AND tags.tag='acoustic') AND (tags.type='mood' AND tags.tag='anger') 
WHERE taglinks.tag_id=tags.id; 

這將返回什麼,如果我刪除了的和部分第二JOIN然後我得到預期的所有曲目標記的聲音,如果我將其更改爲OR我得到這兩個軌道,如預期一樣。

我該如何做一個AND,然後只返回那些同時具有這些標籤和類型的曲目?

在此先感謝:d

編輯:

只是爲了澄清我追求的。我希望能夠檢索既有Acoustic又有Anger作爲標籤的曲目,但只有當這些標籤也符合給定類型時纔可以。

這是因爲後來我可能會有一個名爲jazz的類型爲genre的標記,以及一個名爲jazz的標記爲type style,我需要能夠確保通過正確類型的標記以及標記本身。

以下是我正在使用的sqlfiddle的鏈接 - http://sqlfiddle.com/#!2/aad82/3

Gilles的答案似乎是一個很好的解決方案!

+0

@samsamX - 我會upvote編輯,如果我可以:) – webnoob

+0

我很高興與編輯,你是如何佈置這樣的表? –

回答

1

問題是軌道應該有2個標籤等於問值,發佈的所有請求都不會在這種情況下工作。必須使用INTERSECT sql命令,但是這個在mysql中不可用。

類似的東西應該工作:

SELECT tracks.id, tracks.name 
FROM `taglinks` 
LEFT JOIN tags ON tags.id = taglinks.tag_id 
LEFT JOIN tracks ON tracks.id = taglinks.track_id 
WHERE (
tag = 'accoustic' 
AND `type` = 'genre' 
) 
OR (
tag = 'anger' 
AND `type`= 'mood' 
) 
GROUP BY track_id 
HAVING COUNT(*) =2 
  • 我選擇哪一個匹配至少一個標籤
  • 我算一個GROUP BY匹配塔格數量都行。
  • 如果我搜索兩個參數(這裏accoustic = 'genre'anger = 'mood',發現2排的這條賽道則匹配2個 條件,我把它保持到最後的結果
  • 只要記住 標籤的數量來改變HAVING COUNT(*) =2我們要搜索
+0

這似乎是伎倆,謝謝! :D –

+0

哦,其實這並不完全是這樣,我改變了聲音到foo,它仍然返回軌跡1 –

+0

@DavidHealey - 我們都想出了一個類似的解決方案(雖然我不知道爲什麼人們被任何東西)所以我認爲你問你的問題的方式是誤導性的。你能澄清你的問題嗎? – webnoob

2

這應該是好的

select 
t.name 
from 
tracks as t 
inner join taglinks as tl on t.id = tl.track_id 
inner join tags as tg on tl.tag_id = tg.id 
where 
tg.tag = 'acoustic' and 
tg.type = 'genre' and 
tg.tag = 'anger' and 
tg.type = 'mood'; 

注:我使用as identifier,我更喜歡這種方式,因爲它節省到處寫表名。你不需要。

編輯

我可能誤解了你的問題一點,所以這一次也許有所幫助:

select 
t.name 
from 
tracks as t 
inner join taglinks as tl on t.id = tl.track_id 
inner join tags as tg on tl.tag_id = tg.id 
where 
(tg.tag = 'acoustic' and 
tg.type = 'genre') or 
(tg.tag = 'anger' and 
tg.type = 'mood'); 

這將帶回的是有正確的類型和標記,但沒有結果必須擁有所有這些。

+0

感謝您的及時回覆,這似乎並不完全是我想要的,但它是有用的代碼none-less-less –

+0

@DavidHealey - 你能提供你的數據在http://sqlfiddle.com/的例子嗎?我可以調整查詢,以適應然後 – webnoob

+0

http://sqlfiddle.com/#!2/aad82/4 –

1
SELECT * FROM tracks tracks 
INNER JOIN 
(SELECT taglinks.track_id, COUNT(*) as cnt 
FROM tags tags 
INNER JOIN taglinks taglinks ON taglinks.tag_id = tags.id 
WHERE 
    (tags.tag='ac' AND tags.type='ge') 
    OR (tags.tag='an' AND tags.type='mo') 
GROUP BY taglinks.track_id 
)AS track_match 
    ON track_match.track_id = tracks.id AND track_match.cnt = 2 

您將需要更換 「track_match.cnt = 2」 2 =條件號進行匹配

此搜索解決方案n提供了一些靈活性:您也可以擁有滿足條件的最少條件的曲目。

例如在這裏你可以添加track_match.cnt> = 1,也ORDER BY track_match.cnt DESC

獲得按部就班地進行的配套條件,數量排序的列表。

+0

謝謝,我還沒有嘗試過這一個,因爲我首先遇到了Gilles的解決方案,但我會給它一個去看看它是如何比較:) –

+0

你的作品也是:D –