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

时间:2016-10-26 17:21:59

标签: 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

基本上评论与喜欢的内容存储在同一个表中。

所以表格是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 |
    ----------------------------------------------------------

这些是一些例子,在&#34;活动&#34;在这种情况下的表&#34;类型&#34;将始终等于&#34;评论&#34;。

总结一切和渴望的结果:

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

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

希望这有帮助!

Fiddle link

6 个答案:

答案 0 :(得分:4)

此错误消息

  

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

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

此处的整理问题出现在@prev_value的CROSS JOIN中,需要使用明确的排序规则。

我还将“row_number”逻辑略微更改为单个交叉连接,并将if逻辑移动到选择列表的极值。

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

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

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

    此示例数据针对单个帖子有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标准行为:每个帖子查询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
          ;
    

    See a working demonstration of this query at SQLFiddle

    <强> Results

    |  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条ROWS - 正如预期的那样。最近一条评论的一行,以及下一条最新评论的另一行。这是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
          ;
    

    See the second query working at SQLFiddle

    <强> Results of query 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
    

    See this third query working at SQLFiddle

    <强> Results of query 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连接了最近的两条评论。

    请注意:

    • 问题缺少涵盖所有列的表定义
    • 这个问题缺少任何样本数据,这使您更难理解此处提供的任何结果,但我们也难以准备解决方案
    • 这个问题也缺乏明确的“预期结果”(想要的输出),这导致了回答的进一步复杂性

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

    后记。要包含“跟随”的另一个子查询,您可以使用与已有的子查询类似的子查询。它可以在该子查询之前或之后添加。您也可以在sqlfiddle here

    中看到它正在使用中
    LEFT JOIN (
              SELECT
                    COUNT(*) FollowCNT
                  , IdOtherUser
              FROM Activity
              WHERE type = 'Follow'
              GROUP BY
                    IdOtherUser
              ) F ON USERS.id = F.IdOtherUser
    

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

答案 1 :(得分:2)

我在您的查询中有点迷失,但如果您想一次下载多个帖子的数据,那么在第一个查询中包含评论数据不是一个好主意,因为您将包含有关发布和发布的所有数据用户多次。您应该运行另一个查询来连接带有注释的帖子。类似的东西:

SELECT 
A.UUIDPost, 
C.username,
C.profileImage, 
B.Comment,
B.[DateField]
FROM Posts A JOIN 
Activities B ON A.uuid = B.UUIDPost JOIN
Users C ON B.[UserId] = C.id 

并使用该数据显示您的评论,并注释用户ID,姓名,图片等。

每篇帖子只收到3条评论,你可以查看这篇文章:

Select top 3 values from each group in a table with SQL

如果您确定评论表或此帖子中没有重复的行:

How to select top 3 values from each group in a table with SQL which have duplicates

如果你不确定(虽然由于表中的DateField,它应该是不可能的)。

答案 2 :(得分:1)

UNTESTED:我建议将SQL fiddle和一些示例数据组合在一起,现有的表结构显示问题;这样我们就可以使用您的模式来响应并确保其功能。

因此我们使用变量来模拟窗口函数(例如row_number)

在这种情况下@Row_num和@prev_Value。 @Row_number跟踪每个帖子的当前行(因为单个帖子可能有很多注释)然后当遇到新的帖子ID(UUIDPOST?)时,row_num变量被重置为1.当前记录UUIDPOST匹配时变量@prev_Value,我们只是将行增加1.

此技术允许我们根据日期或活动ID顺序降序分配行号。由于每个交叉连接仅产生1个记录,因此我们不会导致出现重复记录。但是,因为我们因此限制了row_number&lt; = 2我们只在新添加的左连接中获得最近的两条评论。

这假设帖子与用户的关系是多对一,这意味着帖子只能有1个用户。

像这样:虽然我不确定最后的左连接,但我需要更好地理解活动表的结构,从而对原始问题进行评论。

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


  --This join simulates row_Number() over (partition by PostID, order by activityID desc)  (Nice article [here](http://preilly.me/2011/11/11/mysql-row_number/) several other examples exist on SO already.
   --Meaning.... Generate a row number for each activity from 1-X restarting at 1 for each new post but start numbering at the newest activityID)

    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, --Some date or ID desc) Com
       on Com.UUIIDPOSt = Posts.UUID
       and row_number < = 2


  -- Now since we have a row_number restarting at 1 for each new post, simply return only the 1st two rows.

    ORDER BY date DESC
    LIMIT 0, 5

我们必须把and row_number&lt;在连接本身上= 2。如果它被放在where子句中,那么你会丢失这些帖子而没有我认为你仍然需要的任何评论。

此外,我们应该查看“注释”字段以确保它不是空白或空,但请确保它首先起作用。

答案 3 :(得分:0)

此类评论已多次发布,并试图获取“最新的每个”似乎总是一个绊脚石和大多数的加入/子查询噩梦。

特别是对于Web界面,您可能最好将列(或2或3)添加到作为活动“帖子”表的一个表中,例如Latest1,Latest2,Latest3。

然后,通过插入评论表,在表格上插入一个触发器来更新具有最新ID的主帖子。然后你总是在桌面上有这个ID,没有任何子连接。现在,正如您所提到的,您可能希望拥有最后的2个或3个ID,然后添加3个示例列,并将您的插入触发器发布到帖子评论详细信息,对主帖子表进行更新,例如

update PrimaryPostTable
   set Latest3 = Latest2,
       Latest2 = Latest1,
       Latest1 = NewDetailCommentID
   where PostID = PostIDFromTheInsertedDetail

这必须在MySQL下正式化为适当的触发器,但应该很容易实现。您可以使用最新的1来填充列表,然后随着新帖子的发布,它会自动将最新的帖子滚动到他们的第1,第2,第3位置。最后,您的查询可以简化为类似

的内容
Select
      P.PostID,
      P.TopicDescription,
      PD1.WhateverDetail as LatestDetail1,
      PD2.WhateverDetail as LatestDetail2,
      PD3.WhateverDetail as LatestDetail3
   from
      Posts P
         LEFT JOIN PostDetail PD1
            on P.Latest1 = PD1.PostDetailID
         LEFT JOIN PostDetail PD2
            on P.Latest2 = PD2.PostDetailID
         LEFT JOIN PostDetail PD3
            on P.Latest3 = PD3.PostDetailID
   where
      whateverCondition

通常不需要非规范化数据。但是,在这种情况下,它是一个很好的简化器,用于在For-Each类型的查询中获取这些“最新”条目。祝你好运。

这是MySQL中一个完全正常工作的示例,因此您可以通过触发器查看表和sql-inserts的结果以及自动标记以更新主帖表。然后查询帖子表,您可以看到最近的自动滚动到第一,第二和第三位置。最后一个联接显示如何从每个“帖子活动”中提取所有数据

CREATE TABLE Posts
(   id int, 
    uuid varchar(7),
    imageLink varchar(9),
    `date` datetime,
    ActivityID1 int null,
    ActivityID2 int null,
    ActivityID3 int null,
    PRIMARY KEY (id)
);

CREATE TABLE Activity
(   id int, 
    postid int,
    `type` varchar(40) collate utf8_unicode_ci, 
    commentText varchar(20) collate utf8_unicode_ci, 
    `date` datetime,
    PRIMARY KEY (id)
);

DELIMITER //

CREATE TRIGGER ActivityRecAdded
AFTER INSERT ON Activity FOR EACH ROW
BEGIN
    Update Posts
        set ActivityID3 = ActivityID2,
            ActivityID2 = ActivityID1,
            ActivityID1 = NEW.ID
        where
            ID = NEW.POSTID;

END; //

DELIMITER ;



INSERT INTO Posts
    (id, uuid, imageLink, `date`)
    VALUES
    (123, 'test1', 'blah', '2016-10-26 00:00:00');

INSERT INTO Posts
    (id, uuid, imageLink, `date`)
    VALUES
    (125, 'test2', 'blah 2', '2016-10-26 00:00:00');


INSERT INTO Activity
    (id, postid, `type`, `commentText`, `date`)
VALUES
    (789, 123, 'type1', 'any comment', '2016-10-26 00:00:00'),
    (821, 125, 'type2', 'another comment', '2016-10-26 00:00:00'),
    (824, 125, 'type3', 'third comment', '2016-10-27 00:00:00'),
    (912, 123, 'typeAB', 'comment', '2016-10-27 00:00:00');

-- See the results after the insert and the triggers.
-- you will see that the post table has been updated with the 
-- most recent 
-- activity post ID=912 in position Posts.Activity1
-- activity post ID=789 in position Posts.Activity2
-- no value in position Posts.Activity3
select * from Posts;

-- NOW, insert two more records for post ID = 123.
-- you will see the shift of ActivityIDs adjusted
INSERT INTO Activity
    (id, postid, `type`, `commentText`, `date`)
VALUES
    (931, 123, 'type1', 'any comment', '2016-10-28 00:00:00'),
    (948, 123, 'newest', 'blah', '2016-10-29 00:00:00');

-- See the results after the insert and the triggers.
-- you will see that the post table has been updated with the 
-- most recent 
-- activity post ID=948 in position Posts.Activity1
-- activity post ID=931 in position Posts.Activity2
-- activity post ID=912 in position Posts.Activity3
-- notice the FIRST activity post 789 is not there as 
-- anything AFTER the 4th entry, it got pushed away.
select * from Posts;

-- Finally, query the data to get the most recent 3 items for each post.
select
        p.id,
        p.uuid,
        p.imageLink,
        p.`date`,
        A1.id NewestActivityPostID,
        A1.`type` NewestType,
        A1.`date` NewestDate,
        A2.id SecondActivityPostID,
        A2.`type` SecondType,
        A2.`date` SecondDate,
        A3.id ThirdActivityPostID,
        A3.`type` ThirdType,
        A3.`date` ThirdDate
    from
        Posts p
            left join Activity A1
                on p.ActivityID1 = A1.ID
            left join Activity A2
                on p.ActivityID2 = A2.ID
            left join Activity A3
                on p.ActivityID3 = A3.ID;

您可以创建一个测试数据库,以免损坏您的示例。

答案 4 :(得分:0)

这可能会摆脱非法的排序组合......在建立连接后,执行此查询:

SET NAMES utf8 COLLATE utf8_unicode_ci;

关于'最新2'的问题,请使用mysql命令行工具并运行SHOW CREATE TABLE Posts并提供输出。 (同上其他相关表格。)Phpmyadmin(和其他UI)可以在不进入命令行的情况下执行查询。

答案 5 :(得分:0)

通过使用子查询,您可以通过非常简单的查询到达那里。首先,我在where子句中指定用户并加入帖子,因为这对我来说似乎更合乎逻辑。然后我得到了一个带有子查询的帖子的所有喜欢。

现在,我们不是对组大小进行分组和限制,而是通过限制我们当前查看日期之后的日期计数来加入我们想要的值。

INNER JOIN活动,如果您只想显示至少有一条评论的帖子。

SELECT
  u.id,
  u.username,
  u.fullname,
  u.profileImage,
  p.uuid,
  p.caption,
  p.path,
  p.date,
  (SELECT COUNT(*) FROM Activity v WHERE v.uuidPost = p.uuidPost AND v.type = 'like') likes,
  a.commentText,
  a.date
FROM
  Users u INNER JOIN
  Posts p ON p.id = u.id LEFT JOIN
  Activity a ON a.uuid = p.uuid AND a.type = 'comment' AND 2 > (
    SELECT COUNT(*) FROM Activity v
    WHERE v.uuid = p.uuid AND v.type = 'comment' AND v.date > a.date)
WHERE
  u.id = 145

<小时/> 这就是说重新设计可能是最好的,也是性能方面的(Activity很快会包含很多条目,并且它们总是必须按照所需的类型进行过滤)。用户表没有问题,id自动递增并作为主键。对于帖子,我还会添加一个自动递增的id作为主键,user_id作为外键(你也可以决定删除时做什么,例如使用cascade他的所有帖子也会被自动删除)。

对于评论和喜欢你可以使用两个外键user_id和post_id创建单独的表(简单的例子,像这样你只能喜欢帖子而不是别的,但如果没有很多不同类型的喜欢它仍然可以很高兴创建一个post_likes和其他一些......喜欢的表,你必须考虑如何通常查询这些数据,如果这些数据大多是彼此独立的,那么它可能是一个不错的选择。)