当前位置: 首页 > 面试题库 >

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

晏树
2023-03-14
问题内容

我正在尝试获取与我下载的每个帖子相关的最新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

基本上,评论与点赞存储在同一表中。

所以表是Activity,然后我有一列comment存储注释文本,然后“类型”等于“注释”。

可能解释得不是很好,但我愿意尝试并提供尽可能多的细节!

如果有人可以帮助,将不胜感激!!

更新

在https://stackoverflow.com/users/1016435/xqbert给出的此查询中,我目前收到此错误:

操作’=’的排序规则(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

最新编辑

表结构:

帖子

    ----------------------------------------------------------
    | 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 |
    ----------------------------------------------------------

用户

    -------------------------------------------------------------
    | 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 |
    -------------------------------------------------------------

活动

    ----------------------------------------------------------
    | 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 |
    ----------------------------------------------------------

这些是一些示例,在这种情况下,“活动”表中的“类型”将始终等于“注释”。

总结一切和欲望的结果:

当我查询用户帖子时,我希望能够进入“活动”表并为他的每个帖子获取 最新的
2条评论。也许没有评论,所以很明显它将返回0,或者该帖子可能有100条评论。但我只想获取最新/最近的2条评论。

一个例子可能是看Instagram如何做到这一点。对于每个帖子,显示最新的评论1、2或3 …

希望这可以帮助!

小提琴链接


问题答案:

此错误讯息

操作’=’的排序规则(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') ;

[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
      ;

在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 |

有2行-如预期。一行用于最近的注释,另一行用于下一个最近的注释。这是SQL的正常行为,除非在此答案下添加注释,否则问题的读者会认为该正常行为是可以接受的。

这个问题缺乏明确表达的“预期结果”。

[选项1:每个邮政查询一行,最多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
      ;

请参阅在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 |

选项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

请参阅在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 |

概括

我提出了3个查询,每个查询仅显示2条最新注释,但是每个查询以不同的方式进行。第一个查询(默认行为)将为每个帖子显示2行。选项2添加一列,但删除第二行。选项3将最近的2条评论串联起来。

请注意:

  • 这个问题缺少涵盖所有列的表定义
  • 该问题缺少任何示例数据,这使您更难理解此处给出的任何结果,但也使我们更难以准备解决方案
  • 该问题还缺少确定的“预期结果”(所需的输出),这导致答案的进一步复杂性

我确实希望提供的附加信息有用,并且到目前为止,您还知道SQL将数据显示为多行是正常的。如果您不希望这种正常行为,请具体说明您在问题中真正想要的是什么。

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

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

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



 类似资料:
  • 问题内容: 我很好奇为何应该比更快地执行。 当比尔·卡尔文提出一个要点时,我正在回答一个问题。当您使用它时,它使用相关子查询(依赖子查询),而IN()仅使用子查询。 解释显示,并且两者都使用了一个依赖子查询,并且都只使用了一个子查询..所以我很好奇关联子查询如何比子查询更快? 我以前使用过EXISTS,它的执行速度比IN快,这就是我感到困惑的原因。 这是带有说明的SQLFIDDLE 一些问题 在上

  • 问题内容: 一个has_many 。我想检索每天的最新帖子(使用),而忽略其他可能早些写的帖子。提出此问题的另一种方法可能是按部门要求每个最高薪水收入的雇员- 我认为也是一样。 如何在Rails(最好是4.0)中编写此查询?我认为这与它有关,但我似乎无法理解。有没有办法不用SQL来做到这一点? 为了明确起见,我想返回的是一系列post对象,它们是在各自日期上最后写入的对象。 谢谢! 问题答案: 它

  • 问题内容: 谁能看到以下查询出了什么问题? 当我运行它时,我得到: #1064-您的SQL语法有误;检查与您的MySQL服务器版本相对应的手册以获取正确的语法,以在第8行的’a where a.CompetitionID = Competition.CompetitionID’附近使用 问题答案: 主要问题是内部查询不能与外部语句上的子句相关,因为在内部子查询执行之前,where过滤器首先应用于要

  • 问题内容: 我正在尝试使用ajax从数据库中获取每个帖子的所有内容,但是我遇到了一些问题。 这是 问题所在 。 我已经路由了从数据库中获取所有信息的位置,而我没有在这些信息中获取信息。 现在,我想使用Ajax 来获取每个帖子,例如当有人在帖子上发表评论时,应将其添加到数据库中,然后即时从数据库中获取。 注释已通过 Ajax 成功添加,但是我无法使用Ajax从数据库中获取它们。 这是我的 代码 :

  • 帖子评论列表 评论帖子 删除评论 帖子评论列表 get /group-posts/:post/comments 响应 status 200 参数说明 名称 类型 说明 limit integer 默认 20 ,数据返回条数 默认为20 after inegter 可选,上次获取到数据最后一条 ID,用于获取该 ID 之后的数据。 { "pinneds": [],// 置顶评论列表,同com

  • 问题内容: 我正在尝试做的是赋予用户按标签过滤帖子的功能,这样一来,用户 只能看到剩下的要过滤的标签。换句话说,如果用户选择 标签“ tag1”,它将显示具有该标签的帖子,并显示其他帖子,这些帖子 共享但隐藏过滤后没有可见帖子的标签。 我有table的帖子,和标签。具有 和。我已经设法使与特定的标签集一起使用: Let’s say this query gives post_ids 1, 2, 3