如何使用联接来组合这两个查询?

时间:2014-10-21 00:30:26

标签: mysql join

我有两张桌子:文章和修改。我希望用户能够轻松地将文章恢复到原始状态,如果他们意识到他们不应该修改它。我想使用连接,而不是使用额外的查询来查找文章最新修改的ID。所以我想从articles表中获取信息,然后将modify表连接到它以返回关联的行。这就是我现在所拥有的:

<?php

$query = "
     SELECT
          article_id, title, content
     FROM articles
     WHERE article_id = ".$article_id."
     LIMIT 1";

$query_article = $this->db->query($query);
$article = $query_article->row_array();

$query_mod = "
    SELECT
         modification_id, article_id, title, content, date
     FROM modifications
     WHERE article_id = ".$article_id."
     ORDER BY modification_id DESC
     LIMIT 1";

$query_mod = $this->db->query($query);
if($query_mod->num_rows() > 0){
     $mod = $query_mod->row_array();
     $article_title = $mod['title'];
     $article_content = $mod['content'];
} else {
     $article_title = $article['title'];
     $article_content = $article['content'];
}

如何使用连接将这两个查询合并为一个?

SELECT
   a.title, a.content, a.article_id
   m.modification_id AS mod_id, m.title AS mod_title, m.content AS mod_content
FROM articles AS a
LEFT JOIN modifications AS m ON (...)
WHERE a.article_id = 1
LIMIT 1

1 个答案:

答案 0 :(得分:0)

除了空ON子句之外,您对查询的骨干尝试非常正确,只需要在两个表上标识article_id之间的相等性。使用LEFT JOIN是正确的,因为无论modifications中是否匹配,您都需要退回文章。

SELECT
   a.title, a.content, a.article_id,
   m.modification_id AS mod_id, m.title AS mod_title, m.content AS mod_content
FROM 
   articles AS a
   LEFT JOIN modifications AS m ON a.article_id = m.article_id
WHERE a.article_id = 1
ORDER BY mod_id DESC LIMIT 1

但是,您的PHP逻辑显示您有条件地使用title,content表中的modifications(如果存在)。为此,您可以直接在SQL中使用COALESCE()来返回第一个非null参数,因此如果LEFT JOIN没有匹配,将使用article

SELECT
   -- COALESCE to prefer the modifications value if non-null
   COALESCE(m.title,a.title) AS title,
   COALESCE(m.content, a.content) AS content,
   a.article_id,
   m.modification_id AS mod_id
FROM 
   articles AS a
   LEFT JOIN modifications AS m ON a.article_id = m.article_id
WHERE a.article_id = 1
ORDER BY mod_id DESC LIMIT 1

以下是演示http://sqlfiddle.com/#!2/1085c/1

因为您只是尝试返回一个article_id的详细信息,所以不需要子查询。如果您想要返回多个article_id的最新内容,需要使用MAX()聚合的子查询连接,这会变得更复杂。

SELECT
   COALESCE(m.title,a.title) AS title,
   COALESCE(m.content, a.content) AS content,
   a.article_id,
   m.modification_id AS mod_id
FROM 
   articles AS a
   -- Join articles against a subquery to get the most recent mod_id only
   LEFT JOIN (
     SELECT article_id, MAX(modification_id) AS mod_id
     FROM modifications
     GROUP BY article_id
   ) mm ON mm.article_id = a.article_id
   -- and then join that mod_id against the rest of the modifications table
   LEFT JOIN modifications m ON mm.mod_id = m.modification_id
WHERE article_id IN (<multiple criteria for article_id>)

http://sqlfiddle.com/#!2/14051/2