2011-11-30 51 views
2

比方說,我有三個表(MySQL),一個用於用戶,一個用於標記,最後一個用於加入它們(多對多關係):在一個查詢中獲取行及其外鍵行與許多查詢

create table user_tag(
user_id int unsigned not null, 
tag_id int unsigned not null, 
primary_key (user_id, tag_id) 
); 

我想從數據庫中獲取完整的用戶列表(或至少其中很多)以及他們關聯的標籤。我使用PHP作爲服務器語言。

所以我的問題是,是能夠更好地執行一個SQL查詢獲取所有的信息是這樣的:

select user.name, user.image, ..., tag.name from user, tag, user_tag 
    where user.user_id = user_tag.user_id and tag.tag_id = user_tag.tag_id; 

或者是它更好地爲用戶執行一個第一查詢和事後獲取他們的標籤:

select user.name, user.image, ... from user; 

,然後爲每個用戶:

select tag.name from tag, user_tag where tag.tag_id = user_tag.tag_id 
    and user_tag.user_id = $USERID; 

我覺得第二是更好的選擇,但恐怕對數據庫的查詢可能太多(注意,這是一個通用的設計示例,但此模式可以在具有不同表格的數據庫中多次出現)。

哪個更好?優點和缺點?其他方法?

感謝

PS:請不要考慮SQL語法,我沒有檢查出來對一個真正的數據庫,它是唯一的設計問題,謝謝大家

+0

可能重複[JOIN查詢vs多個查詢](http://stackoverflow.com/questions/1067016/join-queries-vs-multiple-queries) – ManseUK

回答

2

我只會考慮兩種選擇:

  1. 一個查詢:

    SELECT user.user_id, user.name, user.image, ..., tag.tag_id, tag.name 
    FROM user 
    LEFT JOIN user_tag ON user.user_id = user_tag.user_id 
    LEFT JOIN tag ON user_tag.tag_id=tag.tag_id 
    
  2. 兩個查詢:

    SELECT user_id, name, image, ... 
    FROM user 
    
    SELECT user_tag.user_id, tag.tag_id, tag.name 
    FROM user_tag 
    INNER JOIN tag ON user_tag.tag_id=tag.tag_id 
    

如果你有100個用戶,有沒有指向100次發出相同的查詢。

我通常是在我只拿到幾列時去#1,否則我去找#2。在這種情況下,你似乎正在檢索一個非常完整的用戶配置文件,所以#2聽起來不錯。

1

這真的取決於許多具體項目,數據庫大小,數據大小,使用情況,併發查詢的數量.....

我建議您嘗試(對於性能)每種方法,並應用最適合您的需求/需求的方法。

我會99%的時間使用一個單一的查詢 - 如果你有所有的relavent索引就位IMO它發送一個單一的查詢....更快的速度更快的編碼,服務器響應方面也使事情有點容易閱讀 - 你可以理解數據庫結構,因爲你可以看到連接 - 你可以在另一個查詢中使用不同的聲音,這可能看起來很混亂。

1

有沒有簡單的答案,這將取決於你的體系結構。找出最好的方法是在您的架構中對兩個解決方案進行基準測試。但是,如果在一個查詢和多個查詢之間進行選擇,只要您的表格索引正確,那麼我將使用一個查詢解決方案。這樣你將節省數據庫連接和文件讀取的開銷。

0

更多選項:

選項3:兩個查詢。首先獲取所有用戶:

select user.name, user.image, ... 
from user 
ORDER BY user_id; 

,然後得到標籤爲所有用戶(以及結合在PHP中2個查詢):

select user_tag.user_id, tag.name 
from tag 
    JOIN user_tag 
    ON tag.tag_id = user_tag.tag_id 
GROUP BY tag.user_id 
ORDER BY tag.user_id 
     , tag.name; 

選項4.獲得所有在一個查詢中,每一個行用戶:

SELECT user.name, user.image, ... 
    , GROUP_CONCAT(tag.name ORDER BY tag_name SEPARATOR ' ') AS tags 
FROM user 
    LEFT JOIN user_tag 
    ON user_tag.user_id = user.user_id 
    LEF JOIN tag 
    ON tag.tag_id = user_tag.tag_id 
GROUP BY user.user_id 
ORDER BY user.user_id;