我有几个表具有多对多关系。 例如表格视频模式
CREATE TABLE `videos` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`description` varchar(10000) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=47606 DEFAULT CHARSET=utf8;
和两个表演员film_actors,例如作家和film_writers
演员和电影演员模式
CREATE TABLE `actors` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `actors_UN` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=152216 DEFAULT CHARSET=utf8;
CREATE TABLE `film_actors` (
`actor_id` int(11) NOT NULL,
`film_id` int(11) NOT NULL,
PRIMARY KEY (`film_id`,`actor_id`),
KEY `FKrs472oyyff3hfwq10pyo94k1d` (`actor_id`),
CONSTRAINT `FK12uvap3je50qd8cq3s0jf7h7r` FOREIGN KEY (`film_id`) REFERENCES `videos` (`id`) ON DELETE CASCADE,
CONSTRAINT `FKrs472oyyff3hfwq10pyo94k1d` FOREIGN KEY (`actor_id`) REFERENCES `actors` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
作家
CREATE TABLE `writers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `writers_UN` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=39875 DEFAULT CHARSET=utf8;
CREATE TABLE `film_writers` (
`film_id` int(11) NOT NULL,
`writer_id` int(11) NOT NULL,
PRIMARY KEY (`writer_id`,`film_id`),
KEY `FKh0kfwnarp6utb4f80ycj1lap` (`film_id`),
CONSTRAINT `FK4hwpb5l48m0xps6jqn1wyjb63` FOREIGN KEY (`writer_id`) REFERENCES `writers` (`id`) ON DELETE CASCADE,
CONSTRAINT `FKh0kfwnarp6utb4f80ycj1lap` FOREIGN KEY (`film_id`) REFERENCES `videos` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
我尝试与演员和作家一起选择电影信息,但结果包含许多重复的行。我使用此sql查询
SELECT
vid.id,
vid.title,
vid.original_title_name,
vid.`year`,
ac.id as actor_id,
ac.name as actor_name,
wr.id as writer_id,
wr.name as writer_name
from
(
select
*
From
videos v
where
v.id = 1722
) vid
JOIN film_actors fa ON
vid.id = fa.film_id
JOIN actors ac ON
fa.actor_id = ac.id
JOIN film_writers fw ON
vid.id = fw.film_id
JOIN writers wr ON
fw.writer_id = wr.id
输出是很多重复行。
id |title |original_title_name |year |actor_id |actor_name |writer_id |writer_name |
-----|----------------|--------------------|-----|---------|-------------------|----------|---------------|
1722 |Назад в будущее |Back to the Future |1985 |1796 |Майкл Дж. Фокс |319 |Боб Гейл |
1722 |Назад в будущее |Back to the Future |1985 |2648 |Джордж ДиЧенцо |319 |Боб Гейл |
1722 |Назад в будущее |Back to the Future |1985 |4807 |Криспин Гловер |319 |Боб Гейл |
1722 |Назад в будущее |Back to the Future |1985 |7601 |Кристофер Ллойд |319 |Боб Гейл |
1722 |Назад в будущее |Back to the Future |1985 |8195 |Лиа Томпсон |319 |Боб Гейл |
1722 |Назад в будущее |Back to the Future |1985 |8707 |Марк МакКлюр |319 |Боб Гейл |
1722 |Назад в будущее |Back to the Future |1985 |9242 |Фрэнсис Ли МакКейн |319 |Боб Гейл |
1722 |Назад в будущее |Back to the Future |1985 |9602 |Уэнди Джо Спербер |319 |Боб Гейл |
1722 |Назад в будущее |Back to the Future |1985 |10545 |Клаудия Уэллс |319 |Боб Гейл |
1722 |Назад в будущее |Back to the Future |1985 |10546 |Томас Ф. Уилсон |319 |Боб Гейл |
1722 |Назад в будущее |Back to the Future |1985 |1796 |Майкл Дж. Фокс |320 |Роберт Земекис |
1722 |Назад в будущее |Back to the Future |1985 |2648 |Джордж ДиЧенцо |320 |Роберт Земекис |
1722 |Назад в будущее |Back to the Future |1985 |4807 |Криспин Гловер |320 |Роберт Земекис |
1722 |Назад в будущее |Back to the Future |1985 |7601 |Кристофер Ллойд |320 |Роберт Земекис |
1722 |Назад в будущее |Back to the Future |1985 |8195 |Лиа Томпсон |320 |Роберт Земекис |
1722 |Назад в будущее |Back to the Future |1985 |8707 |Марк МакКлюр |320 |Роберт Земекис |
1722 |Назад в будущее |Back to the Future |1985 |9242 |Фрэнсис Ли МакКейн |320 |Роберт Земекис |
是否可以通过某种方式将结果转换为类似的内容?
id |title |original_title_name |year |actor_id |actor_name |writer_id |writer_name |
-----|----------------|--------------------|-----|---------|-------------------|----------|---------------|
1722 |Назад в будущее |Back to the Future |1985 |1796 |Майкл Дж. Фокс |319 |Боб Гейл |
1722 |Назад в будущее |Back to the Future |1985 |2648 |Джордж ДиЧенцо |320 |Роберт Земекис |
1722 |Назад в будущее |Back to the Future |1985 |4807 |Криспин Гловер | | |
1722 |Назад в будущее |Back to the Future |1985 |7601 |Кристофер Ллойд | | |
1722 |Назад в будущее |Back to the Future |1985 |8195 |Лиа Томпсон | | |
1722 |Назад в будущее |Back to the Future |1985 |8707 |Марк МакКлюр | | |
1722 |Назад в будущее |Back to the Future |1985 |9242 |Фрэнсис Ли МакКейн | | |
1722 |Назад в будущее |Back to the Future |1985 |9602 |Уэнди Джо Спербер | | |
1722 |Назад в будущее |Back to the Future |1985 |10545 |Клаудия Уэллс | | |
1722 |Назад в будущее |Back to the Future |1985 |10546 |Томас Ф. Уилсон | | |
答案 0 :(得分:1)
之所以会出现“重复”行,是因为一部电影的演员很多,而一部电影的作家很多。电影演员和电影作家之间根本没有关系
用于教育目的的简单查询:
SELECT *
FROM
films
INNER JOIN actors on films.id = actors.filmid
INNER JOIN writers on films.id = writers.filmid
为简化我的观点,它隐藏了表的复杂性,这些复杂性将多对多关系分解为多对一关系
现在。如果一部电影有10位演员和11位作家,则此查询将产生110行
每个演员都将与每个作家相关联
为什么?因为电影演员和电影作家之间绝对没有关系。这两件事根本没有关系。我们没有在JOIN条件下写任何东西来断言某个actor属性等于某个writer属性,因为我们不能-根本没有任何东西可以将它们两个关联在一起>
结果数据库唯一可能做的就是生成一个行集,该行集为每个演员/作家组合都有一行。演员数据重复11次,作家数据重复10次
Actor1/Writer1
Actor1/Writer2
...
Actor2/Writer1
Actor2/Writer2
...
Actor10/Writer11
没有办法解决这个“问题”,这是由于试图将两个无关的东西放到一个查询中而引起的。唯一的“解决方案”是不要将它们放在同一查询中。如果您正在编写像IMDB这样的网站,并且您有一部电影的网页,其中有两个标签,一个用于演员,一个用于作家,请运行两个单独的查询(电影加入演员)和(电影加入作家)来填充数据每个分页-您无法在一个查询中完成*。
*当我说“不能”时,我的意思是“真的不应该”。您发布的“期望结果”网格将演员1796和作家319 毫无缘由地联系在一起-一行中的所有内容都应该是相关的,并且这两个实体除了某些任意对象外,不共享任何关系当ID升序排列时,决定两者均排名第一。尽管有多种方法可以用来关联它们并从查询中消除笛卡尔乘积,但这是一种可怕的代码味道,表明您实际上正在完全解决其他问题(我们看不到)。错误的方式(抱歉)
答案 1 :(得分:-1)
您可以在SELECT语句后使用关键字DISTINCT来启用对非重复行的选择。在这种情况下,将DISTINCT关键字放在第一个SELECT关键字之后应该可以解决您的问题。希望您的问题得到回答