如何用join编写等效的sql查询?

时间:2016-02-14 16:21:22

标签: mysql sql

原始SQL查询:

SELECT *
FROM
  (SELECT p.id,
          p.title,
          p.mark,

     (SELECT max(created)
      FROM comments c
      WHERE c.post_id=p.id
        AND c.mark=1) AS latest_at
   FROM posts p) AS Post
WHERE Post.latest_at IS NOT NULL
ORDER BY latest_at DESC LIMIT 10

我正在尝试使用join编写等效的sql查询。我该怎么办?

mysql> describe posts;
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | int(11)      | NO   | PRI | NULL    | auto_increment |
| user_id     | int(11)      | NO   |     | NULL    |                |
| title       | varchar(255) | NO   |     | NULL    |                |
| body        | text         | YES  |     | NULL    |                |
| category_id | int(11)      | YES  |     | NULL    |                |
| tags        | varchar(50)  | YES  |     | NULL    |                |
| mark        | tinyint(4)   | NO   |     | 1       |                |
| created     | datetime     | YES  |     | NULL    |                |
| modified    | datetime     | YES  |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+

mysql> describe comments;
+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| id       | int(11)      | NO   | PRI | NULL    | auto_increment |
| post_id  | int(11)      | NO   | MUL | NULL    |                |
| name     | varchar(255) | NO   |     | NULL    |                |
| email    | varchar(255) | NO   |     | NULL    |                |
| body     | varchar(500) | NO   |     | NULL    |                |
| mark     | tinyint(4)   | NO   |     | 1       |                |
| created  | datetime     | YES  |     | NULL    |                |
| modified | datetime     | YES  |     | NULL    |                |
+----------+--------------+------+-----+---------+----------------+

任何答案都将受到高度赞赏。提前谢谢。

4 个答案:

答案 0 :(得分:1)

试试这个:

SELECT p.id, p.title, p.mark,
       c.latest_at     
FROM posts p
LEFT JOIN (
   SELECT post_id, MAX(created) AS latest_at
   FROM comments
   WHERE mark = 1
   GROUP BY post_id 
) AS c ON c.post_id = p.id 
WHERE c.latest_at IS NOT NULL
ORDER BY c.latest_at DESC LIMIT 10

或只是这个:

SELECT p.id, p.title, p.mark,
       c.latest_at     
FROM posts p
INNER JOIN (
   SELECT post_id, MAX(created) AS latest_at
   FROM comments
   WHERE mark = 1
   GROUP BY post_id 
) AS c ON c.post_id = p.id 
ORDER BY c.latest_at DESC LIMIT 10

因为第一个查询的c.latest_at IS NOT NULL子句的WHERE谓词将LEFT JOIN变为INNER JOIN

答案 1 :(得分:0)

我建议:

SELECT p.id,
       p.title,
       p.mark,
       c.latest_at
  FROM posts p LEFT OUTER JOIN (select post_id, max(created) latest_at
                                from comments 
                                where mark=1
                                group by post_id
                               ) c ON (c.post_id=p.id)
WHERE c.latest_at IS NOT NULL
ORDER BY c.latest_at DESC LIMIT 10;

答案 2 :(得分:0)

我没有理由重写该查询。相关子查询应具有良好的性能。但是,你可以这样做:

SELECT p.id, p.title, p.mark, c.maxc
FROM posts p JOIN
     (SELECT post_id, MAX(created) as maxc
      FROM comments 
      WHERE mark = 1
      GROUP BY post_id
      ORDER BY maxc DESC
      LIMIT 10
     ) c
     ON c.post_id = p.id
ORDER BY maxc DESC;

注意:

  • 相关子查询现在是一个聚合查询。
  • 这使用JOIN而不是LEFT JOIN,因为(大概)您只想要有评论的行。
  • LIMIT位于子查询中,因此JOIN效率更高。

答案 3 :(得分:0)

我认为公用表表达式也可以使用(不确定性能):

WITH cte_latest (id, maxCreated)
AS
(
   SELECT post_id, MAX(created)
   FROM comments
   WHERE mark = 1
   GROUP BY post_id 
)
SELECT  * -- Whetever columns you need here
FROM    posts p
INNER JOIN cte_latest
    ON p.id = cte_latest.id