讓我們拿SO網站。它有問題和問題有它的標籤。我的問題是,什麼是顯示問題及其標籤的最佳方式。假設他們在不同的表格中。你可以使用SELECT JOIN查詢問題及其標籤嗎?
SELECT * FROM questions RIGHT JOIN tags ON questions.id = tags.question_id
但也有不止一個標籤,所以我們怎麼會一起顯示出來?或者我們只需要做2 SELECTs?因爲如果是的話,那麼它會花費很多資源,因爲我們在一個頁面中顯示多個問題。
讓我們拿SO網站。它有問題和問題有它的標籤。我的問題是,什麼是顯示問題及其標籤的最佳方式。假設他們在不同的表格中。你可以使用SELECT JOIN查詢問題及其標籤嗎?
SELECT * FROM questions RIGHT JOIN tags ON questions.id = tags.question_id
但也有不止一個標籤,所以我們怎麼會一起顯示出來?或者我們只需要做2 SELECTs?因爲如果是的話,那麼它會花費很多資源,因爲我們在一個頁面中顯示多個問題。
首先SO至少需要一個標記,以便不需要right join
,它實際上應該是一個left outer join
,如果你想要做什麼,我覺得你這樣做......
正如你所說,可以有更多而不是一個標籤,這表明我們需要or
或in
或返回多個行或進行某種類型的字符串聚合。
但是,這不會是一個非常好的數據模型,因爲您仍然需要知道該問題的標籤。所以,最好的辦法是將標籤存儲在posts
表格中,而不用擔心tag_id
混亂。
這實際上是這樣做的。
您的查詢(實際上工作)然後是:
select Tags
from Posts
where Id = ?
Tags
是nvarchar(150)
,這對於問題的標籤的分隔列表,在你看到他們對你的問題,如果相同的格式這很有趣!
無論何時輸入新標籤,它都會自動創建標籤,並使用同義詞來確保人們的錯誤拼寫得到糾正。所以,有一個Tags
表Id | TagName
和一個TagSynonoyms
表,(我不知道維基總結保存在哪裏)。然後,您可以在寫入Posts
表之前分配標籤檢查以查看它是否有同義詞並進行更正。
雖則回答你的問題,查詢會(也實際工作):
select p.*, t.TagName
from Posts p
join PostTags pt
on p.Id = pt.PostId
join Tags t
on pt.TagId = t.Id
我不認爲這是什麼,所以實際上沒有 - 我甚至不知道爲什麼會出現一個PostTags
或Tags
表,因爲任何標記都是允許的,不需要執行外鍵查找來檢查標記是否存在。而且沒有必要以這種規範化的方式存儲關係。您只需要Posts
列中的Tags
列和TagSynonyms
表以確保同義詞系統正常工作。然後,如果主鍵不是Id
而是TagName
,則只需要查找一次。
假設tags
表中有一個name
列,我會用GROUP_CONCAT
函數。
SELECT questions.*,
GROUP_CONCAT(DISTINCT tags.name -> ORDER BY tags.id SEPARATOR ',') AS `tag_names`,
GROUP_CONCAT(DISTINCT tags.id -> ORDER BY tags.id SEPARATOR ',') AS `tag_ids`
FROM questions
RIGHT JOIN tags
ON questions.id = tags.question_id
這將顯示2柱tag_names
和tag_ids
其中值將是逗號分隔。當我們獲取值時,我們可以將其分解並獲得真實值。
while($row=mysql_fetch_assoc($result)){
$tag_names = explode("," $row['tag_names'];
$tag_ids = explode("," $row['tag_ids'];
$tags = array_combine($tag_ids, $tag_names);
}
現在$tags
成爲一個關聯數組,其關鍵字是標記ID,值是標記名稱。
如果使用下面的表達式,它會創建一個JSON。但不依賴於它,如果你的標籤名稱有哪些需要轉義的任何字符(例如"
)
Concat('{', GROUP_CONCAT(Concat('"', tags.id, '":"', tags.name, '"')
ORDER BY
tags.id), '}') AS `tag_o`
通過$tags = json_decode($row['tag_o']);
的獲取JSON對象下一個給你一個具體問題的所有標籤。
SELECT * FROM `questions` q INNER JOIN `tags` t ON q.id = t.question_id;
這假定您的標籤表是標籤和問題之間的多對多。
SELECT questions.*, GROUP_CONCAT(CONCAT(tag.id, '::', tag.name))
FROM questions
LEFT JOIN tags
ON questions.id = tags.question_id
LEFT JOIN tag
ON tags.tag_id = tag.id
GROUP BY questions.id
您的標籤表是您的問題表和標籤表之間的多對多嗎? – nnichols 2012-03-03 21:16:14