【问题标题】:Connecting tables when querying in MySQL在 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...
  • 检查我的答案,让我知道哪一个适合你!

标签: php mysql sql wordpress


【解决方案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 语句中的全局对它们进行分组。如果您可以提供数据转储,我可以为您提供有效的查询。
  • 数据来自现场,我不确定客户是否会允许他的数据公开:\对不起
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-25
  • 2012-05-02
  • 2014-11-07
  • 2013-07-13
  • 2013-01-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多