来自三个表的 JOIN 和 GROUP_CONCAT 的意外结果

Unexpected result from JOIN and GROUP_CONCAT with three tables

这是架构的 link 和 sql:http://sqlfiddle.com/#!9/d99b6/8

架构:

create table movies (
  id int,
  movie_name varchar(20)
  );

create table genre (
  movie_id int,
  genre varchar(20)
  );

create table actors (
  movie_id int,
  actor_name varchar(20)
  );

insert into movies (id, movie_name)
  values
    (1, 'asdf');

insert into genre (movie_id, genre)
  values
    (1, 'Comedy'),
    (1, 'Thriller');

insert into actors (movie_id, actor_name) 
  values
    (1, 'actor1'),
    (1, 'actor2');

Sql:

select movies.id,
  movies.movie_name,
  group_concat(genre.genre separator ', ') as genre,
  group_concat(actors.actor_name separator ', ') as actors
from movies
inner join genre on genre.movie_id = movies.id
inner join actors on actors.movie_id = movies.id;

我要输出这个:

id    movie_name    genre               actors
1     asdf          Comedy, Thriller    actor1, actor2

但改用这个:

id    movie_name    genre                                 actors
1     asdf          Comedy, Thriller, Comedy, Thriller    actor1, actor1, actor2, actor2

不确定如何解决这个问题,不胜感激。

你可以使用`distinct:

select m.id, m.movie_name,
       group_concat(distinct g.genre separator ', ') as genres,
       group_concat(distinct a.actor_name separator ', ') as actors
from movies m inner join
     genre g
     on g.movie_id = m.id inner join
     actors a
     on a.movie_id = m.id
group by m.id;

如果每部电影都有大量数据,那么 distinct 会增加额外的开销。 join 对每部电影的类型和演员进行笛卡尔积。您可以通过预聚合或使用相关子查询来处理:

select m.id, m.movie_name,
       (select group_concat(g.genre separator ', ')
        from genre g
        where g.movie_id = m.id 
       ) as genres,
       (select group_concat(a.actor_name separator ', ')
        from actors a
        where a.movie_id = m.id
       ) as actors
from movies m;

只需添加DISTINCT:

select movies.id,
  movies.movie_name,
  group_concat(DISTINCT genre.genre separator ', ') as genre,
  group_concat(DISTINCT actors.actor_name separator ', ') as actors
from movies
inner join genre on genre.movie_id = movies.id
inner join actors on actors.movie_id = movies.id;

SqlFiddleDemo