在 MySQL 中查询时连接表
Posted
技术标签:
【中文标题】在 MySQL 中查询时连接表【英文标题】:Connecting tables when querying in MySQL 【发布时间】:2016-03-28 12:40:21 【问题描述】:我有 3 张桌子:tco_articles
、tco_module_eostext
和 tco_articles_modules
。我的tco_articles
有唯一的id
密钥。每篇文章一个。我的tco_module_eostext
拥有属于每篇文章的唯一instance_id
。
我的tco_articles_modules
包含所有article_id
s,但在其他表中使用的instance_id
s 是9 倍。
所以我可以让article_id
和instance_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_id
s 相同,但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_id
s 对应于 1 个article_id
。这9个中只有一个是正确的,其余的都是空的。 article_id
与tco_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 中查询时连接表的主要内容,如果未能解决你的问题,请参考以下文章