2011-11-25 100 views
0

想象一個物品表。除了主查詢:如何減少標準化數據庫中的查詢數量?

SELECT * From articles WHERE article_id='$id' 

我們還需要其他幾個查詢來獲得

SELECT * FROM users WHERE user_id='$author_id' // Taken from main query 

SELECT tags.tag 
FROM tags 
    INNER JOIN tag_map 
    ON tags.tag_id=tag_map.tag_id 
WHERE article_id='$id' 

和類別,類似的文章幾個查詢等

問題1:是這是使用PHP分別執行這些查詢並處理給定結果的最佳方式,還是有辦法將它們結合起來?

問題2:缺少many-to-many關係(例如tag_id,category_id,author_id標識的每篇文章的標籤,類別,作者);什麼是最好的(最快)是從表格中檢索數據。

回答

3

如果所有的關係是一對多,那麼你可以很容易地檢索一個查詢所有這些數據,如

SELECT 
    [fields required] 
FROM 
    articles a 
    INNER JOIN 
     users u ON a.author_id=u.user_id 
    INNER JOIN 
     tag_map tm ON tm.article_id=a.article_id 
    INNER JOIN 
     tags t t.tag_id=tm.tag_id 
WHERE 
    a.article_id='$id' 

這通常會比三個查詢更快單獨一起爲你的表索引正確因爲MySQL的構建是爲了完成這個任務!這將節省兩次往返數據庫和相關開銷。

+0

對於第二種情況非常好的主意:) – Googlebot

+0

@Ali謝謝你,接受會很好,如果它適合你的話;-) – liquorvicar

+0

這將返回每行多行或** none **如果一篇文章沒有標籤。你可以做,如果你知道,你在做什麼。在任何情況下,我都會在'tag_map'上建議'LEFT JOIN'。 –

0

您可以在標準化表格中添加一個適當的非標準化視圖,其中每條記錄包含您需要的所有數據。或者你可以將SQL調用封裝在存儲過程中,並從你的代碼中調用這些過程,這應該有助於提高性能。證明雙方並獲得難以置信的數字;總是更好地根據證據做出決定而不是想法。 :)

1

您可以在用戶合併在第一個查詢:

SELECT a.*, u.* 
FROM articles a 
JOIN users u ON u.user_id = a.author_id 
WHERE a.article_id='$id'; 

可能做的標籤相同,但將引入在回答一些冗餘,因爲有明顯的多每篇文章的標籤。可能會或可能沒有好處。

在沒有many-to-many關係,這將做的工作一舉,並會在任何情況下優於:

SELECT * 
FROM users u 
JOIN articles a ON a.author_id = u.user_id 
JOIN tag t  USING (tag_id) -- I assume a column articles.tag_id in this case 
WHERE a.article_id = '$id'; 

您可能希望更具選擇性在其列返回。如果標籤不能保證存在,請製作第二個JOIN a LEFT JOIN

+0

@Ali:減少7到6 *是有用的。除此之外,n/m關係還沒有完美的解決方案。它可以是多個查詢或每個查詢多行。唯一的選擇是返回**聚合**,就像每個文章的tag_id數組一樣。 –

+0

如果OP使用MySQL,那麼可以使用'GROUP_CONCAT()'或類似的方法將標記聚合到單個行中,然後通過子查詢中的連接工作到第一個查詢中。雖然在技術上還有2個查詢,但它只會在電線上爲1。 – FtDRbwLXw6

+0

@drrcknlsn:的確如此。 –