【问题标题】:MySQL generate a sublist of comment in a queryMySQL 在查询中生成注释子列表
【发布时间】:2020-07-19 14:10:41
【问题描述】:

我有一个包含 3 个表问题、答案、评论的数据库,它按预期工作,每个问题可以有多个答案,每个答案可以有多个评论

create table Question(
    questionId int primary key auto_increment,
    title varchar(34) not null,
    content TEXT not null
);

create table Answer(
    answerId int primary key auto_increment,
    questionId int not null,
    content TEXT not null
);

create table Comment(
    commentId int primary key auto_increment,
    answerId int,
    questionId int,
    content TEXT not null
);

insert into Question(title, content) values('Testing Question','Testing Question');

insert into Answer(questionId, content) values(1,'Testing Answer 1');
insert into Answer(questionId, content) values(1,'Testing Answer 2');

insert into Comment(answerId, questionId, content) values(1, 1,'Testing Comment 1 to Answer 1');
insert into Comment(answerId, questionId, content) values(1, 1,'Testing Comment 2 to Answer 1');
insert into Comment(answerId, questionId, content) values(2, 1,'Testing Comment 1 to Answer 2');
insert into Comment(answerId, questionId, content) values(2, 1,'Testing Comment 2 to Answer 2');

我希望当我查询一个答案及其 cmets 时,我会在一个 List 中获得这些 cmets,例如:

[
{ answerId: 1, answerContent: 'Answer Content', comments[...]},
{ answerId: 2, answerContent: 'Answer Content', comments[...]}
]

这可能吗?我曾尝试使用此查询:

select * from Answer inner join Comment on Comment.answerId = Answer.answerId where Comment.questionId = 1;

显然它给了我这个:

[
    {
        "answerId" : 1,
        "questionId" : 1,
        "content" : "Testing Answer 1",
        "commentId" : 1,
        "answerId" : 1,
        "questionId" : 1,
        "content" : "Testing Comment 1 to Answer 1"
    },
    {
        "answerId" : 1,
        "questionId" : 1,
        "content" : "Testing Answer 1",
        "commentId" : 2,
        "answerId" : 1,
        "questionId" : 1,
        "content" : "Testing Comment 2 to Answer 1"
    },
    {
        "answerId" : 2,
        "questionId" : 1,
        "content" : "Testing Answer 2",
        "commentId" : 3,
        "answerId" : 2,
        "questionId" : 1,
        "content" : "Testing Comment 1 to Answer 2"
    },
    {
        "answerId" : 2,
        "questionId" : 1,
        "content" : "Testing Answer 2",
        "commentId" : 4,
        "answerId" : 2,
        "questionId" : 1,
        "content" : "Testing Comment 2 to Answer 2"
    }
]

我也尝试过在上一个查询中使用 group by,如下所示:

select * from Answer inner join Comment on Comment.answerId = Answer.answerId where Comment.questionId = 1 group by Comment.questionId;

它还给了我这个:

[
    {
        "answerId" : 1,
        "questionId" : 1,
        "content" : "Testing Answer 1",
        "commentId" : 1,
        "answerId" : 1,
        "questionId" : 1,
        "content" : "Testing Comment 1 to Answer 1"
    }
]

【问题讨论】:

    标签: mysql sql json join


    【解决方案1】:

    你可以使用json_arrayagg():

    select a.*, json_arrayagg(c.content)
    from Answer a inner join
         Comment c
         on c.answerId = a.answerId
    where c.questionId = 1
    group by a.answerId
    

    Here 是一个 dbfiddle。

    如果您想要所有行,即使是没有 cmets 的行,您可以使用:

    select a.*, json_arrayagg(c.content)
    from Answer a left join
         Comment c
         on c.answerId = a.answerId and
            c.questionId = 1
    group by a.answerId
    

    【讨论】:

    • 我已经按照你说的进行了尝试(我还在查询的末尾添加了一个分号)但是它不起作用,无论如何谢谢!
    • @AndreaDattero 。 . .我修正了错字并添加了一个 dbfiddle.
    • 我遇到了一个问题,但是如果我使用您的查询(或其他所有人)时发生这种情况,答案显然也没有评论,它返回给我一个空数组,因为 cmets 不存在回答,因此它没有向我显示整行的内容(回答和评论)有没有办法避免这种情况?我希望如果没有评论,至少它告诉我答案是可能的吗?
    【解决方案2】:

    我只显示答案中的 answerid 和 questions1 其余的是GROUP BY AND GROUP_CONCAT

    select a.answerId, a.questionId, GROUP_CONCAT(DISTINCT a.content) answerContent, GROUP_CONCAT(DISTINCT c.content) comments
    from Answer a inner join Comment c on c.answerId = a.answerId 
    where c.questionId = 1
    GROUP BY a.answerId;
    
    回答ID |问题ID |回答内容 |厘米 --------: | ---------: | :--------------- | :------------------------------------------------ --------- 1 | 1 |测试答案 1 |测试评论 1 到答案 1,测试评论 2 到答案 1 2 | 1 |测试答案 2 |测试评论 1 到答案 2,测试评论 2 到答案 2
    select a.answerId, a.questionId, a.content answerContent, c.content comments
    from Answer a inner join Comment c on c.answerId = a.answerId 
    where c.questionId = 1
    ;
    
    回答ID |问题ID |回答内容 |厘米 --------: | ---------: | :--------------- | :---------------------------- 1 | 1 |测试答案 1 |测试评论 1 到答案 1 1 | 1 |测试答案 1 |测试评论 2 到答案 1 2 | 1 |测试答案 2 |测试评论 1 到答案 2 2 | 1 |测试答案 2 |测试答案 2 的评论 2

    db小提琴here

    【讨论】:

    • 好的,我 +1 你的问题,这可能是一个很好的解决方案(即使我必须在我的 js 文件中拆分 cmets),你对如何做到这一点还有其他想法吗?
    • 您可以删除 GROUP BY 和 GROUPm CONCAT,然后在您的 js 中运行所有行,但据我所知,您已经拥有该解决方案,并且拆分它们并不复杂再次向上循环使用,当然你可以将逗号分隔为另一个字符
    • 是的,我正在考虑循环 json,每次我找到相同的 answerId 时,我都会将评论推送到列表中,当 id 更改时,我会将之前生成的 cmets 列表推送到列表中并开始将下一个 cmets 放入新的不同 answerId 的新列表中,但我认为这不是很有效,我希望 mysql db 为我执行此操作(因为我猜它可能更有效???)
    猜你喜欢
    • 2016-11-21
    • 2017-09-10
    • 2015-09-08
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    • 2019-07-07
    • 1970-01-01
    相关资源
    最近更新 更多