MySQL – 当一个表可能没有对应的行时,如何在查询中组合两个表

我正在用NodeJS和MySQL编写一个基本的CMS系统。 我正在使用WordPress的post的表格结构,即“post”和“post_meta”。

'posts'表有以下几列…

id post_title post_date ...etc 

“post_meta”表格包含以下几列…

 id post_id - ID of associated post meta_key meta_value 

我喜欢这种风格,因为它可以让我的行很容易在SQL编辑器中读取,而不必长时间滚动,也可以根据需要添加额外的元数据。

使用JOIN(下面的查询)我能够创build一个结果集,其中包含来自“posts”的值,以及以“post_meta.meta_key”命名的包含“post_meta.meta_value”值的附加列。

我目前遇到的问题是如何去返回'meta_key'不存在于'posts_meta'表中的结果,而是用NULL填充结果列。

用法示例 2post在'posts'表中,第一个有2个meta_keys与它关联,另一个只有1个。

'post'表格内容

 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)不会作为结果的一部分返回,因为所有正在testing的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中selectmeta_values,并在每个连接的特定键用于检索(在WHERE子句中定义)之后命名它们。

我知道这一定很简单,因为我快到了。 它返回同时具有key1和key2的行,但不包含完全缺less其中一个或全部的行。 我希望它返回所有行,并且如果缺less一个键,请使用NULL填充该行中的该字段

你想要FULL OUTER JOIN而不是LEFT JOIN

Left Join将不包括其他表中不存在的行。 为了有数据(即使它是NULL)。 你需要做一个FULL OUTER JOIN ,这将给你的单元格,而不是完全closures它们。

由于您正在使用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 

SQL加入表