MySQL三表链式左连接,按最后一个表过滤

时间:2015-06-13 13:24:48

标签: mysql sql

我正在尝试找到一种有效的方法来过滤掉由连接的三个表左连接产生的结果集,其中第二个表连接将考虑第三个表的属性。

小提琴:http://sqlfiddle.com/#!2/e319e/2/0

一个简化的例子是三个表之间的连接:帖子,评论和作者。帖子可以有作者写的0..N评论。我想获得一份仅由活跃作者撰写的所有帖子和活跃评论的列表。

考虑以下数据:

发表:

| id |       title |
|----|-------------|
|  1 |  First post |
|  2 | Second post |
|  3 |  Third post |
|  4 |  Forth post |

作者

| id |                  title | is_active |
|----|------------------------|-----------|
|  1 |           First author |         1 |
|  2 |          Second author |         1 |
|  3 |           Third author |         1 |
|  4 | Fourth inactive author |         0 |
|  5 |  Fifth inactive author |         0 |

注释

| id | post_id | author_id |                  title | is_active |
|----|---------|-----------|------------------------|-----------|
|  1 |       1 |         1 |          First comment |         1 |
|  2 |       2 |         1 |         Second comment |         1 |
|  3 |       1 |         2 |          Third comment |         1 |
|  4 |       2 |         4 |         Fourth comment |         1 |
|  5 |       2 |         5 | Fifth inactive comment |         0 |
|  6 |       2 |         3 | Sixth inactive comment |         0 |
|  7 |       4 |         4 |        Seventh comment |         1 |

现在执行简单过滤查询:

SELECT
  p.id post_id, p.title post_title,
  c.id as comment_id, c.title comment, c.is_active active_comment,
  a.id author_id, a.title author, a.is_active active_author
FROM Post p
LEFT JOIN Comment c ON c.post_id = p.id AND c.is_active = 1
LEFT JOIN Author a ON a.id = c.author_id AND a.is_active = 1
ORDER BY p.id;

给我们带来以下结果集:

| id |       title |     id |           title | is_active |     id |         title | is_active |
|----|-------------|--------|-----------------|-----------|--------|---------------|-----------|
|  1 |  First post |      1 |   First comment |         1 |      1 |  First author |         1 |
|  1 |  First post |      3 |   Third comment |         1 |      2 | Second author |         1 |
|  2 | Second post |      2 |  Second comment |         1 |      1 |  First author |         1 |
|  2 | Second post |      4 |  Fourth comment |         1 | (null) |        (null) |    (null) |
|  3 |  Third post | (null) |          (null) |    (null) | (null) |        (null) |    (null) |
|  4 |  Forth post |      7 | Seventh comment |         1 | (null) |        (null) |    (null) |

有两个应该省略的注释 - 由非活动作者编写的“Forth comment”和“Seventh comment”。

我认为唯一可行的方法是为Comment

添加JOIN条件
AND c.id IN (SELECT id FROM Author WHERE is_active = 1)

产生正确的结果集,但我猜不是很优化。但是我找不到任何其他有效的解决方案。有什么方法可以以某种方式优化它吗?谢谢!

3 个答案:

答案 0 :(得分:0)

我想你想要这个from条款:

FROM Post p LEFT JOIN
     (Comment c JOIN
      Author a
      ON a.id = c.author_id AND a.is_active = 1 and c.is_active = 1
     )
     ON c.post_id = p.id

正如我在评论中提到的那样,您可能希望停用非活动作者的评论。这将涉及触发器或存储过程。

哦,你很有礼貌地提出了一个SQL小提琴,所以here它正在发挥作用。

答案 1 :(得分:0)

如果你想省略"第三篇文章"也是(只有活跃的作者),你可以试试这个:

 SELECT 
  p.id post_id, p.title post_title,
  c.id as comment_id, c.title comment, c.is_active active_comment,
  a.id author_id, a.title author, a.is_active active_author
 FROM Post p
 LEFT JOIN Comment c ON c.post_id = p.id 
 LEFT JOIN Author a ON a.id = c.author_id
 WHERE c.is_active = 1 AND a.is_active = 1
 ORDER BY p.id;

答案 2 :(得分:0)

这也应该这样做:

select a.title, p.title, c.title 
from author a 
left join comment c on a.id = c.author_id
left join post p on c.post_id = p.id
where a.id in (select id from author where is_active = 1) 
and c.is_active = 1

http://sqlfiddle.com/#!2/e319e/1