2011-11-30 98 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;