【问题标题】:show last comment which just 1 comment per user [duplicate]显示最后一条评论,每个用户只有 1 条评论 [重复]
【发布时间】:2016-08-03 08:48:15
【问题描述】:

我有一个普通的 cmets 表:

| id | comment | date | user | post | status |

我想获取我最后的 10 个 cmets,每个用户只有 1 条评论,我的意思是这样的:

我有这些数据: | id | comment | date | user | post | | 1 | text1 | 2016-04-01| 1 | 1 | | 2 | text2 | 2016-04-02| 2 | 1 | | 3 | text3 | 2016-04-03| 1 | 2 | | 4 | text4 | 2016-04-04| 4 | 3 | | 5 | text5 | 2016-04-04| 3 | 5 | | 6 | text6 | 2016-04-05| 2 | 4 | | 7 | text7 | 2016-04-07| 5 | 3 | | 8 | text8 | 2016-04-10| 4 | 9 | | 9 | text9 | 2016-04-11| 3 | 7 | | 10 | text10 | 2016-04-12| 5 | 8 |

我想得到这个: | 10 | text10 | 2016-04-12| 5 | 8 | | 9 | text9 | 2016-04-11| 3 | 7 | | 8 | text8 | 2016-04-10| 4 | 9 | | 6 | text6 | 2016-04-05| 2 | 4 | | 3 | text3 | 2016-04-03| 1 | 2 |

我使用这个sql语句:

SELECT  *
FROM  `comments`
GROUP BY  `user` 
ORDER BY MAX(`id`) DESC

这会获取用户的正确顺序但评论日期顺序错误的 cmets: | 7 | text7 | 2016-04-07| 5 | 3 | | 9 | text9 | 2016-04-11| 3 | 7 | | 4 | text4 | 2016-04-04| 4 | 3 | | 6 | text6 | 2016-04-05| 2 | 4 | | 1 | text1 | 2016-04-01| 1 | 1 |

【问题讨论】:

标签: mysql greatest-n-per-group


【解决方案1】:

为什么它不适用于GROUP BY

SELECT *不能与GROUP BY一起使用;它是无效的 SQL。 GROUP BY 不选择表格行。它使用提供的表达式创建行组,然后从每个组中生成一条新记录,并使用表达式中涉及的值计算该新记录的每一列。

SELECT 子句中出现的列必须满足以下规则之一:

虽然* 是查询所用表的所有列名的快捷方式,但对于您的查询,只有user 列满足上述要求之一。

Before version 5.7.5 MySQL 没有实现上面的第三条规则。它曾经接受包含在不遵循任何GROUP BY 要求的SELECT 子句列中的查询。此类列的查询返回值为indeterminate。

自 5.7.5 版起,MySQL 拒绝满足要求的 GROUP BY 查询。

解决办法

无论哪种方式,您的问题的解决方案都不涉及GROUP BY。在正确的条件下使用LEFT JOIN 可以轻松完成:

SELECT lc.*
FROM comments lc               # 'lc' from 'last comment'
    LEFT JOIN comments nc      # 'nc' from 'newer comment'
        ON lc.user = nc.user   # both comments belong to the same user
        AND lc.id < nc.id      # 'nc' is newer than 'lc'
WHERE nc.id IS NULL            # there is no 'newer comment'
ORDER BY lc.id DESC
LIMIT 10

工作原理

它加入表comments,别名为lc(“lc”来自用户的“最后评论”),别名为nc(“nc”来自“较新的评论”)。 join 子句将 lc 的每个条目与属于同一用户 (lc.user = nc.user) 且较新 (lc.id &lt; nc.id) 的所有 nc 条目匹配;我假设 ID 是按顺序分配的,较新的 cmets 具有更大的值id)。

使用LEFT JOIN 确保lc 的每一行都出现在连接结果中,即使在nc 中没有找到匹配的行(因为没有同一用户的更新评论)。在这种情况下,使用NULL 代替nc 的字段。 WHERE 子句在最终结果集中只保留nc.id 中具有NULL 的行;这意味着在lc 部分中,它们包含每个用户的最新评论。

SELECT 子句包含lc 的所有字段(无论如何nc 的字段都是NULL)。 ORDER BY 子句可用于对结果集进行排序。 ORDER BY lc.id DESC 将最近的 cmets 放在首位,LIMIT 子句将结果集保持在合适的大小。

【讨论】:

    【解决方案2】:

    你可以试试这个:

    SELECT u.*
    FROM (
        SELECT id,comment,MAX(date) as date,`user`,post,status
        FROM comments 
        GROUP BY `user`) AS t
    JOIN comments AS u USING (id)
    

    【讨论】:

      猜你喜欢
      • 2011-12-10
      • 2019-02-17
      • 1970-01-01
      • 2020-01-09
      • 2011-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-17
      相关资源
      最近更新 更多