我有两张桌子:文章和修改。我希望用户能够轻松地将文章恢复到原始状态,如果他们意识到他们不应该修改它。我想使用连接,而不是使用额外的查询来查找文章最新修改的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
答案 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>)