来自三个表的 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;
这是架构的 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;