MYSQL查询 - 获取与帖子相关的最新评论

10 php mysql sql greatest-n-per-group

我正在尝试获取与我下载的每个帖子相关的最新1或2条评论,有点像instagram,因为它们显示每个帖子的最新3条评论,到目前为止我收到的帖子和喜欢的数量.

现在我需要做的就是弄清楚如何获得最新的评论,不太确定如何处理它,这就是为什么我希望有更多专业知识的人可以帮助我!

这是我目前的查询:

(SELECT
        P.uuid,
        P.caption,
        P.imageHeight,
        P.path,
        P.date,
        U.id,
        U.fullname,
        U.coverImage,
        U.bio,
        U.username,
        U.profileImage,
        coalesce(Activity.LikeCNT,0),
        Activity.CurrentUserLiked
        FROM USERS AS U
        INNER JOIN Posts AS P 
        ON P.id = U.id
        LEFT JOIN (SELECT COUNT(DISTINCT Activity.uuidPost) LikeCNT, Activity.uuidPost, Activity.id, sum(CASE WHEN Activity.id = $id then 1 else 0 end) as CurrentUserLiked
        FROM Activity Activity
        WHERE type = 'like' 
        GROUP BY Activity.uuidPost) Activity
        ON Activity.uuidPost = P.uuid
        AND Activity.id = U.id
        WHERE U.id = $id)
UNION
        (SELECT 
        P.uuid,
        P.caption,
        P.imageHeight,
        P.path,
        P.date,
        U.id,
        U.fullname,
        U.coverImage,
        U.bio,
        U.username,
        U.profileImage,
        coalesce(Activity.LikeCNT,0),
        Activity.CurrentUserLiked
        FROM Activity AS A
        INNER JOIN USERS AS U 
        ON A.IdOtherUser=U.id
        INNER JOIN Posts AS P 
        ON P.id = U.id
        LEFT JOIN (SELECT COUNT(DISTINCT Activity.uuidPost) LikeCNT, Activity.uuidPost, Activity.id, sum(CASE WHEN Activity.id = $id then 1 else 0 end) as CurrentUserLiked
    FROM Activity Activity
    WHERE type = 'like' 
    GROUP BY Activity.uuidPost) Activity
    ON Activity.uuidPost = P.uuid
    AND Activity.id = U.id
    WHERE A.id = $id)
    ORDER BY date DESC
    LIMIT 0, 5
Run Code Online (Sandbox Code Playgroud)

基本上,评论存储在与喜欢的表相同的表中.

所以表是Activity,然后我有一个comment存储注释文本的列,然后"类型"等于"注释".

可能没有很好的解释,但我愿意尝试尽可能多的细节!

如果有人可以帮助它非常感谢!!

UPDATE

/sf/users/71150481/给出的此查询中,我目前收到此错误:

操作'='的非法混合排序(utf8_general_ci,IMPLICIT)和(utf8_unicode_ci,IMPLICIT)

SELECT Posts.id,
    Posts.uuid,
    Posts.caption,
    Posts.path,
    Posts.date,
    USERS.id,
    USERS.username,
    USERS.fullname,
    USERS.profileImage,
    coalesce(A.LikeCNT,0),
    com.comment
FROM Posts 
INNER JOIN USERS 
  ON Posts.id = 145 
 AND USERS.id = 145
LEFT JOIN (SELECT COUNT(A.uuidPost) LikeCNT, A.UUIDPost
    FROM Activity A
    WHERE type =  'like' 
    GROUP BY A.UUIDPOST) A
 on A.UUIDPost=Posts.uuid
LEFT JOIN (SELECT comment, UUIDPOST, @row_num := IF(@prev_value=UUIDPOST,@row_num+1,1) as row_number,@prev_value := UUIDPOST
           FROM Activity 
           CROSS JOIN (SELECT @row_num := 1) x
           CROSS JOIN (SELECT @prev_value := '') y
           WHERE type = 'comment'
           ORDER BY UUIDPOST, date DESC) Com
  ON Com.UUIIDPOSt = Posts.UUID
 AND row_number <= 2
ORDER BY date DESC
LIMIT 0, 5
Run Code Online (Sandbox Code Playgroud)

最新编辑

表结构:

帖子

    ----------------------------------------------------------
    | id         | int(11)      |                 | not null |
    | uuid       | varchar(100) | utf8_unicode_ci | not null |
    | imageLink  | varchar(500) | utf8_unicode_ci | not null |
    | date       | timestamp    |                 | not null |
    ----------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

USERS

    -------------------------------------------------------------
    | id            | int(11)      |                 | not null |
    | username      | varchar(100) | utf8_unicode_ci | not null |
    | profileImage  | varchar(500) | utf8_unicode_ci | not null |
    | date          | timestamp    |                 | not null |
    -------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

活动

    ----------------------------------------------------------
    | id           | int(11)      |                 | not null |
    | uuid         | varchar(100) | utf8_unicode_ci | not null |
    | uuidPost     | varchar(100) | utf8_unicode_ci | not null |
    | type         | varchar(50)  | utf8_unicode_ci | not null |
    | commentText  | varchar(500) | utf8_unicode_ci | not null |
    | date         | timestamp    |                 | not null |
    ----------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

这些是一些例子,在"活动"表格中,"type"将始终等于"comment".

总结一切和渴望的结果:

当我查询用户帖子时,我希望能够进入"活动"表并获得他所拥有的每个帖子的最新 2条评论.也许没有评论所以很明显它会返回0,也许这篇文章可能有100条评论.但我只想获得最新/最近的2条评论.

一个例子可以看看Instagram是如何做到的.对于每个帖子,显示最近的评论1,2或3 ....

希望这可以帮助!

小提琴链接

Use*_*ady 4

这个错误信息

操作“=”时非法混合排序规则 (utf8_general_ci,IMPLICIT) 和 (utf8_unicode_ci,IMPLICIT)

通常是由于列和表的定义造成的。它通常意味着等号的两侧有不同的排序规则。您需要做的是选择一个并将该决定包含在您的查询中。

这里的排序规则问题出现在 @prev_value 的 CROSS JOIN 中,它需要使用显式排序规则。

我还稍微将“row_number”逻辑更改为单个交叉连接,并将 if 逻辑移至选择列表的最末端。

下面显示了一些示例数据。需要示例数据来测试查询。任何试图用工作示例回答您的问题的人都需要数据。我把它放在这里的原因是双重的。

  1. 这样你就会明白我提出的任何结果
  2. 这样以后当你问另一个 SQL 相关问题时,你就会明白提供数据的重要性。您这样做不仅对我们来说更方便。如果提问者提供了示例数据,那么提问者就已经理解了它——这不会是某个花费了一些时间来提供帮助的陌生人的发明。

样本数据

请注意,表中缺少某些列,仅包含表详细信息中指定的列。

此示例数据针对单个帖子有 5 条评论(未记录点赞)

CREATE TABLE Posts 
(
`id` int, 
`uuid` varchar(7) collate utf8_unicode_ci,
`imageLink` varchar(9) collate utf8_unicode_ci, 
`date` datetime
 );
    
INSERT INTO Posts(`id`, `uuid`, `imageLink`, `date`)
VALUES
(145, 'abcdefg', 'blah blah', '2016-10-10 00:00:00') ;

CREATE TABLE   USERS
(
`id` int, 
`username` varchar(15) collate utf8_unicode_ci,
 `profileImage` varchar(12) collate utf8_unicode_ci,
 `date` datetime
) ;
        
INSERT INTO     USERS(`id`, `username`, `profileImage`, `date`)
VALUES
(145, 'used_by_already', 'blah de blah', '2014-01-03 00:00:00') ;
    
    
CREATE TABLE Activity
(
`id` int, 
`uuid` varchar(4) collate utf8_unicode_ci, 
`uuidPost` varchar(7) collate utf8_unicode_ci,
 `type` varchar(40) collate utf8_unicode_ci, 
`commentText` varchar(11) collate utf8_unicode_ci, `date` datetime
) ;
        
INSERT INTO Activity (`id`, `uuid`, `uuidPost`, `type`, `commentText`, `date`)
 VALUES
(345, 'a100', 'abcdefg', 'comment', 'lah lha ha', '2016-07-05 00:00:00'),
(456, 'a101', 'abcdefg', 'comment', 'lah lah lah', '2016-07-06 00:00:00'),
(567, 'a102', 'abcdefg', 'comment', 'lha lha ha', '2016-07-07 00:00:00'),
(678, 'a103', 'abcdefg', 'comment', 'ha lah lah', '2016-07-08 00:00:00'),
(789, 'a104', 'abcdefg', 'comment', 'hla lah lah', '2016-07-09 00:00:00') ;
Run Code Online (Sandbox Code Playgroud)

[SQL 标准行为:每个 Post 查询 2 行]

这是我最初的查询,有一些更正。我更改了选择列表的列顺序,以便当我呈现结果时您可以轻松地看到一些与评论相关的数据。请研究它们提供的结果,以便您了解查询的作用。由于我已经指出的原因,我正在使用的示例数据中不存在以 # 开头的列。

SELECT
      Posts.id
    , Posts.uuid
    , rcom.uuidPost
    , rcom.commentText
    , rcom.`date` commentDate 
    #, Posts.caption
    #, Posts.path
    , Posts.`date`
    , USERS.id
    , USERS.username
    #, USERS.fullname
    , USERS.profileImage
    , COALESCE(A.LikeCNT, 0) num_likes
FROM Posts
INNER JOIN USERS ON Posts.id = 145
            AND USERS.id = 145
LEFT JOIN (
          SELECT
                COUNT(A.uuidPost) LikeCNT
              , A.UUIDPost
          FROM Activity A
          WHERE type = 'like'
          GROUP BY
                A.UUIDPOST
          ) A ON A.UUIDPost = Posts.uuid 
LEFT JOIN (
      SELECT
            @row_num := IF(@prev_value=UUIDPOST,@row_num+1,1) as row_number
          , commentText
          , uuidPost
          , `date`
          , @prev_value := UUIDPOST
      FROM Activity
      CROSS JOIN ( SELECT @row_num := 1, @prev_value := '' collate utf8_unicode_ci  ) xy
      WHERE type = 'comment'
      ORDER BY
            uuidPost
          , `date` DESC
      ) rcom ON rcom.uuidPost  = Posts.UUID
            AND rcom.row_number <= 2
ORDER BY
      posts.`date` DESC
      ;
      
      
Run Code Online (Sandbox Code Playgroud)

在 SQLFiddle 中查看此查询的工作演示

结果

|  id |    uuid | uuidPost | commentText |                   date |                      date |  id |        username | profileImage | num_likes |
|-----|---------|----------|-------------|------------------------|---------------------------|-----|-----------------|--------------|-----------|
| 145 | abcdefg |  abcdefg | hla lah lah | July, 09 2016 00:00:00 | October, 10 2016 00:00:00 | 145 | used_by_already | blah de blah |         0 |
| 145 | abcdefg |  abcdefg |  ha lah lah | July, 08 2016 00:00:00 | October, 10 2016 00:00:00 | 145 | used_by_already | blah de blah |         0 |
Run Code Online (Sandbox Code Playgroud)

有 2 行 - 正如预期的那样。一行用于最新评论,另一行用于下一个最新评论。这是 SQL 的正常行为,在该答案下添加注释之前,问题的读者会认为这种正常行为是可以接受的。

该问题缺乏明确阐述的“预期结果”。


[选项 1:每个 Post 查询一行,最多 2 条评论,添加列]

在下面的评论中,我们发现您不希望每个帖子有 2 行,这将是一个简单的解决方案。嗯,这很简单,但是有一些选项,并且这些选项是由用户以需求的形式指定的。如果问题有“预期结果”,那么我们就会知道选择哪个选项。尽管如此,这是一种选择

SELECT
      Posts.id
    , Posts.uuid
    , max(case when rcom.row_number = 1 then rcom.commentText end) Comment_one
    , max(case when rcom.row_number = 2 then rcom.commentText end) Comment_two
    #, Posts.caption
    #, Posts.path
    , Posts.`date`
    , USERS.id
    , USERS.username
    #, USERS.fullname
    , USERS.profileImage
    , COALESCE(A.LikeCNT, 0) num_likes
FROM Posts
INNER JOIN USERS ON Posts.id = 145
            AND USERS.id = 145
LEFT JOIN (
          SELECT
                COUNT(A.uuidPost) LikeCNT
              , A.UUIDPost
          FROM Activity A
          WHERE type = 'like'
          GROUP BY
                A.UUIDPOST
          ) A ON A.UUIDPost = Posts.uuid 
LEFT JOIN (
      SELECT
            @row_num := IF(@prev_value=UUIDPOST,@row_num+1,1) as row_number
          , commentText
          , uuidPost
          , `date`
          , @prev_value := UUIDPOST
      FROM Activity
      CROSS JOIN ( SELECT @row_num := 1, @prev_value := '' collate utf8_unicode_ci  ) xy
      WHERE type = 'comment'
      ORDER BY
            uuidPost
          , `date` DESC
      ) rcom ON rcom.uuidPost  = Posts.UUID
            AND rcom.row_number <= 2
GROUP BY
      Posts.id
    , Posts.uuid
    #, Posts.caption
    #, Posts.path
    , Posts.`date`
    , USERS.id
    , USERS.username
    #, USERS.fullname
    , USERS.profileImage
    , COALESCE(A.LikeCNT, 0)
ORDER BY
      posts.`date` DESC
      ;
Run Code Online (Sandbox Code Playgroud)

查看在 SQLFiddle 上运行的第二个查询

查询2的结果

|  id |    uuid | Comment_one | Comment_two |                      date |  id |        username | profileImage | num_likes |
|-----|---------|-------------|-------------|---------------------------|-----|-----------------|--------------|-----------|
| 145 | abcdefg | hla lah lah |  ha lah lah | October, 10 2016 00:00:00 | 145 | used_by_already | blah de blah |         0 |
Run Code Online (Sandbox Code Playgroud)

** 选项 2,将最新评论连接到单个逗号分隔列表 **

SELECT
      Posts.id
    , Posts.uuid
    , group_concat(rcom.commentText) Comments_two_concatenated
    #, Posts.caption
    #, Posts.path
    , Posts.`date`
    , USERS.id
    , USERS.username
    #, USERS.fullname
    , USERS.profileImage
    , COALESCE(A.LikeCNT, 0) num_likes
FROM Posts
INNER JOIN USERS ON Posts.id = 145
            AND USERS.id = 145
LEFT JOIN (
          SELECT
                COUNT(A.uuidPost) LikeCNT
              , A.UUIDPost
          FROM Activity A
          WHERE type = 'like'
          GROUP BY
                A.UUIDPOST
          ) A ON A.UUIDPost = Posts.uuid 
LEFT JOIN (
      SELECT
            @row_num := IF(@prev_value=UUIDPOST,@row_num+1,1) as row_number
          , commentText
          , uuidPost
          , `date`
          , @prev_value := UUIDPOST
      FROM Activity
      CROSS JOIN ( SELECT @row_num := 1, @prev_value := '' collate utf8_unicode_ci  ) xy
      WHERE type = 'comment'
      ORDER BY
            uuidPost
          , `date` DESC
      ) rcom ON rcom.uuidPost  = Posts.UUID
            AND rcom.row_number <= 2
GROUP BY
      Posts.id
    , Posts.uuid
    #, Posts.caption
    #, Posts.path
    , Posts.`date`
    , USERS.id
    , USERS.username
    #, USERS.fullname
    , USERS.profileImage
    , COALESCE(A.LikeCNT, 0)
ORDER BY
      posts.`date` DESC
      
Run Code Online (Sandbox Code Playgroud)

请参阅在 SQLFiddle 上运行的第三个查询

查询3的结果

|  id |    uuid | Comments_two_concatenated |                      date |  id |        username | profileImage | num_likes |
|-----|---------|---------------------------|---------------------------|-----|-----------------|--------------|-----------|
| 145 | abcdefg |    hla lah lah,ha lah lah | October, 10 2016 00:00:00 | 145 | used_by_already | blah de blah |         0 |
Run Code Online (Sandbox Code Playgroud)

** 概括 **

我提出了 3 个查询,每个查询仅显示 2 个最新评论,但每个查询都以不同的方式执行此操作。第一个查询(默认行为)将为每个帖子显示 2 行。选项 2 添加一列但删除第二行。选项 3 连接 2 个最新评论。

请注意:

  • 该问题缺少涵盖所有列的表定义
  • 该问题缺乏任何示例数据,这使您更难理解此处提供的任何结果,也让我们更难准备解决方案
  • 该问题还缺乏明确的“预期结果”(想要的输出),这导致回答更加复杂

我确实希望所提供的附加信息会有一些用处,并且现在您也知道 SQL 将数据呈现为多行是正常的。如果您不希望出现这种正常行为,请在问题中具体说明您真正想要的是什么。


后记。要包含另一个“follows”子查询,您可以使用与已有子查询类似的子查询。它可以添加在该子查询之前或之后。您还可以在 sqlfiddle中看到它的使用

LEFT JOIN (
          SELECT
                COUNT(*) FollowCNT
              , IdOtherUser
          FROM Activity
          WHERE type = 'Follow'
          GROUP BY
                IdOtherUser
          ) F ON USERS.id = F.IdOtherUser
Run Code Online (Sandbox Code Playgroud)

虽然添加另一个子查询可能会满足您对更多信息的需求,但总体查询可能会随着数据的增长而变慢。一旦确定了真正需要的功能,就值得考虑这些表上需要哪些索引。(我相信建议您单独寻求该建议,如果确实这样做,请确保包括 1. 表的完整 DDL 和 2. 查询的解释计划。)