数据库模式

create table `questions` (
  `id` int not null auto_increment,
  `title` varchar(45) not null,
  primary key (`id`));

create table `tags` (
  `id` int not null auto_increment,
  `question_id` int not null,
  `name` varchar(45) not null,
  primary key (`id`));

create table `comments` (
  `id` int not null auto_increment,
  `question_id` int not null,
  `body` varchar(45) not null,
  primary key (`id`));

insert into questions (title) values
("title1"), ("title2"), ("title3");

insert into tags (question_id, name) values
(1, "javascript"), (1, "php"), (1, "c#"), (2, "mysql"), (2, "php"), (3, "c#");

insert into comments (question_id, body) values
(1, "comment1"), (1, "comment1"), (1, "comment2"), (3, "comment3");

这就是它在视觉上的样子:
questions
| id |  title |
|----|--------|
|  1 | title1 |
|  2 | title2 |
|  3 | title3 |
tags
| id | question_id |       name |
|----|-------------|------------|
|  1 |           1 | javascript |
|  2 |           1 |        php |
|  3 |           1 |         c# |
|  4 |           2 |      mysql |
|  5 |           2 |        php |
|  6 |           3 |         c# |
comments
| id | question_id |     body |
|----|-------------|----------|
|  1 |           1 | comment1 |
|  2 |           1 | comment1 |
|  3 |           1 | comment2 |
|  4 |           3 | comment3 |

每个问题必须至少有一个标签。它也可以有 0 条或更多条评论。对于一个问题,同一正文可以有两条评论。

期望输出

我想选择所有问题,即它们的ID,标题,标签和评论。

输出应如下所示:
| id |  title |       tags        |          comments          |
|----|--------|-------------------|----------------------------|
|  1 | title1 | c#,php,javascript | comment1,comment1,comment2 |
|  2 | title2 | php,mysql         | (null)                     |
|  3 | title3 | c#                | comment3                   |

解决问题的尝试

我尝试了以下查询:
select questions.id, questions.title,
  group_concat(tags.name), group_concat(comments.body)
from questions
join tags on questions.id = tags.question_id
left join comments on questions.id = comments.question_id
group by questions.id

不幸的是,它没有按预期工作。它产生以下输出:
| id |  title | group_concat(distinct tags.name) |                                                      group_concat(comments.body) |
|----|--------|----------------------------------|----------------------------------------------------------------------------------|
|  1 | title1 |                c#,php,javascript | comment1,comment1,comment1,comment2,comment2,comment2,comment1,comment1,comment1 |
|  2 | title2 |                        php,mysql |                                                                           (null) |
|  3 | title3 |                               c# |                                                                         comment3 |

如您所见,对于第一个问题,每个评论我都会收到三遍,因为这个问题有三个标签。

另外,评论的顺序不对。它们应与插入时的顺序相同,即comment1,comment1,comment2,而不是comment1,comment2,comment1

我不能使用 distinct 进行评论,因为在一个问题上可以有多个评论与同一正文。

我知道这可以用嵌套的select解决,但是据我所知,它将对查询的性能产生巨大的负面影响。

SQL fiddle

The SQL Fiddle 与数据库架构和我的查询。

最佳答案

您需要先聚合并应用 GROUP_CONCAT 然后加入:

select questions.id, questions.title,
       tags.name, comments.body
from questions
join (
   select question_id, group_concat(tags.name) as name
   from tags
   group by question_id
) tags on questions.id = tags.question_id
left join (
   select question_id, group_concat(comments.body) as body
   from comments
   group by question_id
) comments on questions.id = comments.question_id

关于mysql - 在 MySQL 中具有多个连接的 group_concat,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37432077/

10-11 01:12