MySQL - 当一个表可能没有对应的行时,如何在查询中组合 2 个表
Posted
技术标签:
【中文标题】MySQL - 当一个表可能没有对应的行时,如何在查询中组合 2 个表【英文标题】:MySQL - How to combine 2 tables in a query when one table may not have a corresponding row 【发布时间】:2015-11-13 08:17:27 【问题描述】:我正在用 NodeJS 和 mysql 编写一个基本的 CMS 系统。我正在为 WordPress 也使用的帖子使用表结构,即“帖子”和“post_meta”。
“posts”表包含以下列...
id
post_title
post_date
...etc
“post_meta”表具有以下列...
id
post_id - ID of associated post
meta_key
meta_value
我喜欢这种风格,因为它使我的行在 SQL 编辑器中易于阅读,而无需滚动很长的长度,以及根据需要添加额外的元数据。
使用 JOIN(下面的查询)我能够创建一个包含来自“posts”的值的结果集,以及以“post_meta.meta_key”命名的包含“post_meta.meta_value”值的其他列。
我目前遇到的问题是如何返回“posts_meta”表中不存在“meta_key”的结果,而是用 NULL 填充结果的该列。
示例用法。 'posts' 表中有 2 个帖子,第一个有 2 个关联的 meta_key,另一个只有 1 个。
“帖子”表格内容
id : 1
title : 'Post 1'
post_date : 'timestamp of posted date/time'
id : 2
title : 'Post 2'
post_date : 'timestamp of posted date/time'
'posts_meta' 表格内容
id : 1
post_id : 1
meta_key : 'key1'
meta_value : 'key1 value'
id : 2
post_id : 1
meta_key : 'key2'
meta_value : 'key2 value'
id : 3
post_id : 2
meta_key : 'key1'
posts_meta.meta_value : 'key1 value'
我想从中得到的结果是
post_id : 1
title : 'Post 1'
post_date : 'timestamp of posted date/time'
key1 : 'key1 value'
key2 : 'key2 value'
post_id : 2
title : 'Post 2'
post_date : 'timestamp of posted date/time'
key1 : 'key1 value'
key2 : NULL
但是,对于我当前正在使用的代码,第二个结果(Post 2)不会作为结果的一部分返回,只有“Post 1”,因为正在测试的所有 meta_keys 都存在于“ post_meta' 表。
这是我目前的 SQL 代码(已编辑以保留上面的示例)
SELECT
posts.id,
posts.title,
posts.post_date,
m1.meta_value as `key1`,
m2.meta_value as `key2`
FROM posts
LEFT JOIN post_meta as m1 ON ( posts.id = m1.post_id )
LEFT JOIN post_meta as m2 ON ( posts.id = m2.post_id )
WHERE
( m1.meta_key = 'key1' )
AND ( m2.meta_key = 'key2' )
ORDER BY posts.post_date DESC
如您所见,我从 2 个 JOIN 中选择 meta_values,并在每个连接用于检索的特定键之后命名它们(如 WHERE 子句中定义的那样)。
我知道这一定很简单,因为我快到了。它返回同时具有 key1 和 key2 的行,但不返回完全缺少其中一个或全部的行。我希望它返回所有行,如果缺少键,则用 NULL 填充该行中的字段
【问题讨论】:
full outer join
,可能。 A left join B
将返回来自 A 的所有记录,以及来自 B 的任何匹配记录。如果 B 中没有可用的记录,则 B 字段将为空。但如果没有 A 记录,则左连接不会为您“创建”这些记录。
完全外连接不是 MySQL 的一部分
【参考方案1】:
你想要FULL OUTER JOIN
而不是LEFT JOIN
。
Left Join
不会包含其他表中不存在的行。为了有数据(即使它是NULL)。你需要做一个FULL OUTER JOIN
,它会给你的单元格为NULL,而不是完全关闭它们。
由于您使用的是 MySQL,因此您必须使用 UNION
模拟 FULL OUTER JOIN
的行为。像这样的:
SELECT
posts.id,
posts.title,
posts.post_date,
m1.meta_value as `key1`,
m2.meta_value as `key2`
FROM posts
LEFT JOIN post_meta as m1 ON ( posts.id = m1.post_id )
LEFT JOIN post_meta as m2 ON ( posts.id = m2.post_id )
WHERE
( m1.meta_key = 'key1' )
AND ( m2.meta_key = 'key2' )
ORDER BY posts.post_date DESC
UNION
SELECT
posts.id,
posts.title,
posts.post_date,
m1.meta_value as `key1`,
m2.meta_value as `key2`
FROM posts
RIGHT JOIN post_meta as m1 ON ( posts.id = m1.post_id )
LEFT JOIN post_meta as m2 ON ( posts.id = m2.post_id )
WHERE
( m1.meta_key = 'key1' )
AND ( m2.meta_key = 'key2' )
ORDER BY posts.post_date DESC
UNION
SELECT
posts.id,
posts.title,
posts.post_date,
m1.meta_value as `key1`,
m2.meta_value as `key2`
FROM posts
RIGHT JOIN post_meta as m1 ON ( posts.id = m1.post_id )
RIGHT JOIN post_meta as m2 ON ( posts.id = m2.post_id )
WHERE
( m1.meta_key = 'key1' )
AND ( m2.meta_key = 'key2' )
ORDER BY posts.post_date DESC
【讨论】:
因为我使用的是 MySQL,所以我无法使用 'FULL OUTER JOIN',因为它不是 MySQL 的一部分 @Rob 更新以考虑 MySQL 支持。 太棒了!在发现 FULL OUTER JOIN 不在 MySQL 中之后,大多数主题都指向 UNION 是我需要的,并且您的更新证实了这一点。第二个问题,如果示例扩展到更多元键,比如 3 或 4,那么 RIGHT/LEFT 连接需要如何编写。我看到上面有左/左,右/左,右/右。 3 个键、4 个或 5 个键需要什么? 一直在尝试您提供的代码示例,但对于没有 key2 的帖子,它仍然没有返回任何结果。我会继续研究问题可能是什么以上是关于MySQL - 当一个表可能没有对应的行时,如何在查询中组合 2 个表的主要内容,如果未能解决你的问题,请参考以下文章
当可能没有更新行时,使用 Codeigniter 检查 db->update 是不是成功