如何高效地从多个表中查询子记录?

Posted

技术标签:

【中文标题】如何高效地从多个表中查询子记录?【英文标题】:How to efficiently sql query child records from multiple tables? 【发布时间】:2010-02-19 15:32:42 【问题描述】:

我们有一个简单的数据库。 User 表保存用户。 Accounts 表为每个用户保存多个帐户。主题表包含每个帐户的多个主题。

因此,一个用户将有多个帐户,每个帐户将有多个主题。那么,如果我有一个 id=1 的用户,我如何有效地查询所有 3 个表以获取该用户的所有帐户和主题?

我目前正在使用运行许多 sql 查询的 foreach 循环。有没有办法只运行一个 sql 查询来得到我想要的??

这是我目前正在使用的代码(即 CodeIgniter 代码):

$data=array();
$accounts=$this->db->get_where('accounts',array('user_id'=>1));
foreach ($accounts->result() as $account) 
    $tmp=array();
    $topics=$this->db->get_where('topics',array('account_id'=>$account->id));
    foreach ($topics->result() as $topic) 
        $this->db->order_by($order_by);
        $terms=$this->db->get_where('terms',array('topic_id'=>$topic->id));
        array_push($tmp,array('topic'=>$topic, 'terms'=>$terms->result()));
    
    array_push($data,array('account'=>$account, 'topics'=>$tmp));

return $data;

【问题讨论】:

您在寻找 SQL 连接吗?还是使用 codeignitor 的更优雅的 php 语法? 应该在 SQL 端多做一些,这是数据问题而不是 UI 问题。 如果其中一个帐户还没有任何主题怎么办?你还不想找回那个账号吗?条款也是如此。如果一个主题没有任何条款怎么办?是否仍要检索主题?也许这些情况是不可能的,但如果是,它们就是重要的细节。 @chris - 那么你会使用左连接 【参考方案1】:

简单的一对多与另一个一对多。

用户->许多帐户

帐户->许多主题

想想您的用户表,其中一行是唯一的(包含一位用户,比如 Jon Doe)。 想想您的帐户表引用了某种用户(即多个帐户可以包含同一个用户,此外,帐户 Acme 1 和 Acme 2 都属于用户 Jon Doe)。 最后,考虑一下包含对帐户的引用的主题表。也就是说,每个主题都有一个帐户 ID。这意味着帐户有许多与之相关的主题。

SELECT
   u.UserID,
   a.Account
   t.Topic
FROM 
    Users u
INNER JOIN 
     Accounts a
ON u.UserID = a.UserID
INNER JOIN
     Topics t
ON t.AccountID = a.AccountID

如果您想缩小一个用户范围,只需添加一个WHERE 子句:

SELECT
   u.UserID,
   a.Account
   t.Topic
FROM 
    Users u
INNER JOIN 
     Accounts a
ON u.UserID = a.UserID
INNER JOIN
     Topics t
ON t.AccountID = a.AccountID
WHERE u.UserID=1

【讨论】:

它运作良好,尽管它似乎希望“a.Account”和“t.Topic”成为 Accounts 和 Topics 表中的特定字段。我可以使用“'SELECT u.id as user_id, a.id as account_id, t.id as topic_id ...”获取特定字段,但是有没有办法选择整个记录而不是必须指定每个字段? 如果你想要每条记录,你可以用通配符选择 u.*, t.* ... 等等。虽然我建议不要使用通配符...你应该总是列出每个字段 没关系,我是从下面的 dkantowitz 那里得到的:“SELECT u.*, a.*, t.* ...”【参考方案2】:
SELECT top.`topic_id` [etc]
FROM `accounts` acc
JOIN `topics` top ON (top.`account_id` = acc.`id`)
WHERE acc.`member_id` = 1

是基本查询,不确定CI。

如果您需要会员 ID 中的其他信息,那么:

SELECT usr.`id`, acc.`account_id`, top.`topic_id` [etc]
FROM `users` usr
JOIN `accounts` acc ON (acc.`member_id` = usr.`id`)
JOIN `topics` top ON (top.`account_id` = acc.`id`)
WHERE usr.`id` = 1

【讨论】:

以上是关于如何高效地从多个表中查询子记录?的主要内容,如果未能解决你的问题,请参考以下文章

sql主表分页查询关联子表取任意一条高效方案

如何使用具有多个结果的子查询将值插入表中?

如何正确使用连接/子查询从多个表中选择数据? (PHP-MySQL)

如何优化限制查询以更快地从大表中访问数据?

使用来自 SELECT 子查询的值的 UPDATE 查询,高效

MySQL 查询版本控制表中存在多个版本记录如何实现只取最大版本号对应记录