考虑存储在MySQL数据库中的这两个表。第一个存储电影列表,第二个存储关于每个电影的元数据。它们不是将“类别”和“演员”字段添加到电影表中,而是作为键/值对存储在movie_attributes表中,因为每个电影可能有多个类别或参与者归属于它。
影
id name
-----------
0 hot rod
1 star wars
movie_attributes
id movie_id key value
----------------------------------------
0 0 genre comedy
1 0 genre stupid
2 0 actor andy samberg
3 0 actor harrison ford
4 0 actor chester tam
5 1 genre adventure
6 1 actor harrison ford
根据允许用户选择多个流派和多个演员的搜索条件,查询电影的最有效方法是什么?如果用户在搜索中添加了多个类别,我希望结果包含两个类别的电影(但只包括那些也与所选演员相匹配的视频。)
例如,这个伪查询:
select * from movies where (genre = 'comedy' OR genre = 'adventure') AND (actor = 'harrison ford')
会返回这个:
id name
-----------
0 hot rod
1 star wars
目前,我的解决方案使用了大量的子查询并且速度非常慢,因为我的数据库每个电影(流派,演员,演员,标签等)包含两个以上的属性键类型,而且速度非常慢。这是真正的查询,它等同于上面的示例伪查询:
select * from movies
WHERE (select count(*) from movie_attributes
WHERE key='genre'
AND (value='comedy'
OR value='adventure'))>0
AND
(select count(*) from movie_attributes
WHERE key='actor'
AND (value='harrison ford'))>0
使用连接或其他一些我不熟悉的SQL巫术魔法是否有更有效的方法来实现相同的结果?谢谢!
答案 0 :(得分:0)
看看这个是否有帮助:
SELECT m.* FROM `movie_attributes` ma
JOIN `movies` m ON (ma.movie_id=m.id)
WHERE
(`key` = 'genre' and `value` in ('comedy', 'adventure'))
OR (`key` = 'actor' and `value` in ('harrison ford'))
其次,请确保key, value
movie_attributes
上有索引
答案 1 :(得分:0)
SELECT *
FROM movies
WHERE EXISTS(
SELECT NULL
FROM movie_attributes
WHERE movies.id = movie_attributes.movie_id AND
key = 'genre' AND value in ('comedy', 'adventure')
) AND
EXISTS(
SELECT NULL
FROM movie_attributes
WHERE movies.id = movie_attributes.movie_id AND
key = 'actor' AND value = 'harrison ford'
)
但我建议不要采用这种设计,请参阅@n8wrl answer。