在 MySQL 中查询时连接表

Posted

技术标签:

【中文标题】在 MySQL 中查询时连接表【英文标题】:Connecting tables when querying in MySQL 【发布时间】:2016-03-28 12:40:21 【问题描述】:

我有 3 张桌子:tco_articlestco_module_eostexttco_articles_modules。我的tco_articles 有唯一的id 密钥。每篇文章一个。我的tco_module_eostext 拥有属于每篇文章的唯一instance_id。 我的tco_articles_modules 包含所有article_ids,但在其他表中使用的instance_ids 是9 倍。

所以我可以让article_idinstance_id 在您查询tco_module_eostext 时返回空。

我想做一个查询,为正确的文章返回正确的正文。

到目前为止我有:

global $wpdb;
$posts = array();

$ids = $wpdb->get_results('SELECT DISTINCT instance_id, article_id FROM tco_articles_modules', ARRAY_A);

这将返回包含所有实例和 ID 的数组,例如:

Array
(
    [0] => Array
        (
            [instance_id] => 928615
            [article_id] => 129396
        )

    [1] => Array
        (
            [instance_id] => 928616
            [article_id] => 129396
        )

    [2] => Array
        (
            [instance_id] => 928617
            [article_id] => 129396
        )

    [3] => Array
        (
            [instance_id] => 928618
            [article_id] => 129396
        )

您可以看到article_ids 相同,但instance_id。当你放

$wpdb->get_results('SELECT body FROM tco_module_eostext WHERE instance_id=928617 ', ARRAY_A);

你可能会变得空虚,但对于

$wpdb->get_results('SELECT body FROM tco_module_eostext WHERE instance_id=928618 ', ARRAY_A);

你可以有一些正文。

这是我的问题。我需要遍历所有这些并过滤掉非空的并为它们分配正确的文章。我设法输出了文章

foreach ($ids as $key => $value) 
    $instance_ID = $value['instance_id'];
    $article_ID = $value['article_id'];

    $article_out = $wpdb->get_results('SELECT * FROM tco_articles WHERE id='.$article_ID.' ', ARRAY_A);
    $posts[$article_ID] = $article_out[0];


返回类似:

Array
(
    [129396] => Array
        (
            [id] => 129396
            [headline] => Bla bla bla title
            [intro] => This is cool article intro
            [needs_review] => 0
            [published] => 2014-12-16 09:17:00
            [unpublished] => 
            [hidden] => 0
            [no_single_page] => 0
            [permalink] => link-perma-link-here
            [internal_slug] => 
            [type_id] => 3
            [thread_id] => 0
            [news_id] => 0
            [header_game_id] => 0
            [puff_hh_id] => 0
            [puff_title] => 
            [hdrcol_id] => 900
            [review_queued] => 
            [lock_timeout] => 0
            [created] => 2014-12-16 09:17:00
            [updated] => 2015-01-16 13:51:30
            [created_by] => 84142
            [updated_by] => 84142
        )
    ...

现在我想从tco_module_eostext 表中追加body 文本。

是否有一个查询可以让我自动执行此操作,或者同时执行此操作,然后附加到 $posts 数组?

当你有 180000+ 个帖子时,foreach 查询方法有点慢。

感谢任何帮助。

【问题讨论】:

所以,tco_module_eostext 可以有多个 body 文本,因为您可以有多个 instance_id 相关。如果有多个,你想要哪一个?最新的(按 instance_id DESC)? 对于tco_module_eostext 表中的每个instance_id,都附有一个body 文本(每个ID 都是唯一的)。但是我没有办法找出这篇文章属于哪篇文章,除非我通过tco_articles_modules,其中包含 9 个instance_ids 对应于 1 个article_id。这9个中只有一个是正确的,其余的都是空的。 article_idtco_articles 表中的id 相同。 所以,您可以肯定,tco_module_eostext 中总是只有一行,每个 9 instance_ids (其中之一)? 是的,我已经对其进行了测试,据我所见,只有九分之一的人始终存在。我的意思是我没有检查 180000 中的每一个 :D 所以我会说我有 98% 的把握。我没有建立数据库,我只是将它迁移到 wp... 检查我的答案,让我知道哪一个适合你! 【参考方案1】:

如果您确定每个article_id 中始终只有一行tco_module_eostext,您可以使用JOIN(内连接),它只会为每个article_id 显示一行。

SELECT a.*, t.body
FROM tco_articles a
JOIN tco_articles_modules m ON m.article_id = a.id
JOIN tco_module_eostext t ON m.instance_id = t.instance_id
//WHERE .....

但是,如果在其他两个表中没有针对该article_id 的条目,这将不会显示某些文章的任何行。但仍有办法解决这个问题。我们可以使用LEFT OUTER JOIN,然后确保仅在tco_module_eostext 中有任何instace_id 的行时才进行连接。这将确保您在其他表中没有数据时至少从tco_articles 表中获取文章信息。

SELECT a.*, t.body
FROM tco_articles a
LEFT OUTER JOIN tco_articles_modules m ON m.article_id = a.id AND EXISTS ( SELECT NULL FROM tco_module_eostext WHERE instance_id = m.instance_id )
LEFT OUTER JOIN tco_module_eostext t ON m.instance_id = t.instance_id
//WHERE .....

【讨论】:

据我所知,这起到了作用。您在第一部分有一个小错误:JOIN tco_articles_modules m ON m.article_id = a.id,因为文章表中的主键只是 id。但它返回了附加了正文的数组。谢谢!这对我有很大帮助! :) 我可能需要稍微修改一下,以包括我的数据库的其余部分,但至少现在我知道如何开始 :) 没有 foreach 有很大帮助!再次感谢你:)【参考方案2】:

为什么不使用带有连接的查询?

未测试!

SELECT
    article.*,
    text.body as bodytext
FROM
    tco_articles_modules AS modules LEFT OUTER JOIN
    tco_module_eostext AS text ON
        modules.instance_id = text.instance_id LEFT OUTER JOIN
    tco_articles AS article ON
        article.id = modules.article_id

它应该从tco_articles_modules获取所有分配了article_id的文章

查看 OUTER Join - 您可能希望将其替换为 INNER JOIN 以获得更快的查询。此外,您可能需要一个 WHERE 条件来在查询中进行过滤。还要注意 mysql 表中的正确索引 - 每个连接列都应该被索引 - 这将获得更快的结果。

【讨论】:

注意,可能存在重复数据! 我会试一试,看看结果如何 :) 是的,也可能存在重复数据。如果有,您必须通过 ON 语句或 GROUP BY 语句中的全局对它们进行分组。如果您可以提供数据转储,我可以为您提供有效的查询。 数据来自现场,我不确定客户是否会允许他的数据公开:\对不起

以上是关于在 MySQL 中查询时连接表的主要内容,如果未能解决你的问题,请参考以下文章

在 MySQL 中查询时连接表

MySQL多表连接查询

TypeORM 无关联关系的mysql多表连接查询

在单个查询中使用 PHP 连接两个 mysql 表

MySQL多表连接查询实例

教你快速掌握MySQL数据库——连接查询语句 内连接