MySQL加入左行只有第一个右行

时间:2014-07-02 10:07:23

标签: mysql sql join relational-database

假设我们有一个简单的博客文章表,例如:

aid  title  content
1    Foo    Lorem Ips…
2    Bar    Dolor Sit…
3    Boo    Amet Cons…

...还有另一个评论表:

cid  aid  name    comment                date
1    1    zaphod  First!                 1404294939
2    1    arthur  Not you again!!111     1404296182 
3    1    marvin  It’s all useless anyw… 1404299811 

现在我想生成一份包含相应文章最新评论的所有文章的列表。这意味着我必须离开加入articles表上的comments表,但是对于每个文章行,我只希望评论行具有最高date值或换句话说:只有我为每篇文章评论连接ORDER BY date DESC LIMIT 1做第一行。

最好(或最简单)的方法是什么?

4 个答案:

答案 0 :(得分:3)

您只能使用联接来执行此操作。它比Sub查询快得多。

 select articles.*,comments1.* from 
    Articles articles
    LEFT JOIN (Comments comments1
    LEFT JOIN Comments comments2 on comments1.date<comments2.date 
and comments1.aid=comments2.aid
    ) on comments2.cid IS NULL and comments1.aid=articles.aid;

SQLFiddle示例:http://sqlfiddle.com/#!2/51a5bb/4

答案 1 :(得分:1)

所需的方法是首先找到每篇文章的最新评论日期:

SELECT  aid, MAX(Date) AS Date
FROM    Comments
GROUP BY aid;

然后,您可以将此逻辑放在子查询中,并使用aiddate联接回到评论,以获取所有字段:

SELECT  c.*
FROM    Comments AS c
        INNER JOIN
        (   SELECT  aid, MAX(Date) AS Date
            FROM    Comments
            GROUP BY aid
        ) AS mc
            ON mc.aid = c.aid
            AND mc.Date = c.Date;

然后,您可以在“约会”表格中添加联接。如果所有文章都有评论,或者您只想要带有评论的文章,​​那么您可以使用:

SELECT  *
FROM    Articles AS a
        INNER JOIN Comments AS c
            ON c.Aid = a.aid
        INNER JOIN
        (   SELECT  aid, MAX(Date) AS Date
            FROM    Comments
            GROUP BY aid
        ) AS mc
            ON mc.aid = c.aid
            AND mc.Date = c.Date;

如果不是,您将需要使用带括号的LEFT JOIN来确保子查询上的INNER JOIN不会删除没有注释的文章:

SELECT  *
FROM    Articles AS a
        LEFT JOIN (Comments AS c
            INNER JOIN
            (   SELECT  aid, MAX(Date) AS Date
                FROM    Comments
                GROUP BY aid
            ) AS mc
                ON mc.aid = c.aid
                AND mc.Date = c.Date)
            ON c.Aid = a.aid;

<强> Example on SQL Fiddle

这实际上只是简写:

SELECT  *
FROM    Articles AS a
        LEFT JOIN 
        (   SELECT  c.*
            FROM    Comments AS c
                    INNER JOIN
                    (   SELECT  aid, MAX(Date) AS Date
                        FROM    Comments
                        GROUP BY aid
                    ) AS mc
                        ON mc.aid = c.aid
                        AND mc.Date = c.Date
        ) AS c
            ON c.Aid = a.aid;

但是,由于MySQL实现了所有子查询,这避免了Comments的无法实现的实现。这两个查询中的Comparing the execution plans表明前者会表现得更好。

答案 2 :(得分:0)

使用group by语句查找每篇文章的最后评论日期。使用它来加入文章和最后评论。

select a.*, c.*
from articles a
join
(
  select aid, max(date) as date
  from comments
  group by aid
) last_comment on (last_comment.aid = a.aid)
join comments c on (c.aid = last_comment.aid and c.date = last_comment.date);

答案 3 :(得分:0)

select title,contents,name,coment from articles join comment
using(aid) where date =(select max(date) from comment group by aid);