在一个查询中获取行及其外键行与许多查询

时间:2011-11-30 08:52:49

标签: php mysql database foreign-keys

假设我有三个表(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;

我觉得第二个是更好的选择,但我担心对数据库的查询可能太多(请注意,这是一般设计示例,但此模式可以在具有不同表的数据库上多次出现)。 / p>

哪个更好?优点和缺点?其他方式?

由于

PS:请不要考虑SQL语法,我还没有对真实数据库进行检查,这只是设计问题,谢谢

4 个答案:

答案 0 :(得分: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
    
  3. 如果你有100个用户,那么发出100次相同的查询是没有意义的。

    当我只提取几列时,我通常会选择#1,否则我会选择#2。在这种情况下,您似乎正在检索一个非常完整的用户配置文件,因此#2听起来不错。

答案 1 :(得分:1)

这实际上取决于许多特定项目,数据库大小,数据大小,使用情况,并发查询数量.....

我建议您尝试(表现)每种方法并应用最符合您要求/需求的方法。

我99%的时间都会使用一个查询 - 如果你有所有的相关索引IMO它发送单个查询的速度要快得多....在编码,服务器响应和制作东西方面更快更容易阅读 - 你可以理解数据库结构,因为你可以看到连接 - 你可以在另一个查询中使用不同的alises,这可能看起来很混乱。

答案 2 :(得分:1)

对此没有简单的答案,因为这取决于您的架构。找出的最佳方法是在您的架构中对这两个解决方案进行基准测试。但是,如果在一个查询和多个查询之间进行选择,只要您的表被正确编入索引,那么我将使用一个查询解决方案。这样你就可以节省数据库连接和文件读取的开销。

答案 3 :(得分: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;