2012-02-15 106 views
0
select 
    film.title 
from film 
    left outer join filmitem ON film.filmid = filmitem.filmid 
    left outer join filmgenre ON filmitem.filmid = filmgenre.filmid 
where 
    film.title = title and filmgenre.genre NOT IN (
    select genre from genre 
    where genre != 'Comedy' and genre != 'Horror') 
group by title; 

我想找到僅包含流派'喜劇'和'恐怖'的電影。當我運行這個查詢時,我得到了喜劇和其他性別的電影,但我想排除其他性別,只獲得只有喜劇和恐怖的電影。有什麼建議嗎?sql查找特定流派的電影

+0

當然,如果你想匹配「喜劇」或「(‘喜劇’,‘恐怖’)......和流派」,「恐怖」,那麼你只需要一個 – kaj 2012-02-15 13:27:08

+0

@JohnSmith:會不會有永遠至少有一種類型分配給af ILM? – 2012-02-15 13:36:09

回答

5
select 
    film.title 
from film 
    left outer join filmitem ON film.filmid = filmitem.filmid 
    left outer join filmgenre ON filmitem.filmid = filmgenre.filmid 
where 
    film.title = title and filmgenre.genre IN ('Comedy', 'Horror') 
group by title; 

UPD:啊,對不起,第二次讀你的問題。將更新查詢在一分鐘...

UPD2:如果您需要選擇只有兩個流派「喜劇」和「恐怖」電影,那麼你可以使用

select 
    film.title 
from film 
    left outer join filmitem ON film.filmid = filmitem.filmid 
where 
    film.title = title 
    AND EXISTS (SELECT * FROM filmgenre fg WHERE filmitem.filmid = fg.filmid AND fg.genre='Comedy') 
    AND EXISTS (SELECT * FROM filmgenre fg WHERE filmitem.filmid = fg.filmid AND fg.genre='Horror') 
    AND NOT EXISTS (SELECT * FROM filmgenre fg WHERE filmitem.filmid = fg.filmid AND fg.genre NOT IN ('Comedy','Horror')) 
group by title; 

雖然我很確保有更高效的方法來做到這一點...

+0

這正是你想要的。如果你選擇了多個字段(比如id),我會提出一個建議,像Sergey那樣做,並在列IE前添加表名前綴:film.id,genre.id,film.title – gorelative 2012-02-15 13:29:14

+1

@Mike:如果我正確理解OP,他需要選擇只有'Comedy'和'Horror'的電影,並省略「喜劇」,「恐怖」和「冒險」等電影。這將需要更復雜的查詢。 – 2012-02-15 13:31:28

+0

啊,我也錯過了。 @OP你如何存儲流派列表?如果它的逗號分隔我認爲IN仍然可以工作,不是嗎? – gorelative 2012-02-15 13:35:30

3

如果你只需要電影標題,下面應該提供最佳性能。似乎沒有必要在select語句中加入連接,並且當然不需要將它們留在外連接中。

SELECT Title 
FROM Film 
WHERE FilmID IN (SELECT FilmID FROM FilmGenre WHERE Genre IN ('Comedy', 'Horror')) 

或在某些RDBMS連接是比子查詢更爲有效where子句(Read more...

SELECT Film.Title 
FROM Film 
     INNER JOIN 
     ( SELECT FilmID 
      FROM FilmGenre 
      WHERE Genre IN ('Comedy', 'Horror') 
      GROUP BY FilmID 
     ) g 
      ON g.FileID = Film.FilmID 

編輯:

如果需要什麼樣的電影是僅喜劇和恐怖然後你需要類似的東西:

SELECT Film.Title 
FROM Film 
     INNER JOIN 
     ( SELECT FilmID 
      FROM FilmGenre 
      GROUP BY FilmID 
      HAVING COUNT(DISTINCT CASE WHEN Genre IN ('Comedy', 'Horror') THEN Genre END) = 2 
      AND COUNT(DISTINCT Genre) = 2 
     ) g 
      ON g.FileID = Film.FilmID 

同樣的邏輯仍然應用根據RDBMS將子查詢移動到IN子句中進行優化。

+0

將會返回屬於其他類型的電影,以及'喜劇'和'恐怖'。 – 2012-02-15 13:33:14

+0

閱讀。 – GarethD 2012-02-15 13:40:28

0

嘗試:

select title from film f 
where not exists 
(select null 
from filmgenre g 
where f.filmid = g.filmid and 
     g.genre NOT IN ('Comedy', 'Horror') 
) 

(假設總是會有分配給電影的至少一個流派。)

編輯:可替代地,如果有可以是不分配給任何類型的膜,嘗試:

select max(f.title) title 
from film f 
join filmgenre g on f.filmid = g.filmid 
group by f.filmid 
having count(distinct g.genre) = 
     count(distinct case when g.genre in ('Comedy', 'Horror') then g.genre end) 
+1

這並不能保證選定的電影確實有'喜劇'和'恐怖'的流派 – 2012-02-15 13:32:55

+0

如果總是至少有一種類型被分配給一部電影,它將會是。 – 2012-02-15 13:35:29

+0

編輯仍然不能按需要工作。如果一部電影只在電影中有「喜劇」條目,那麼HAVING條款的每一邊都將爲1,因此它將會變成真實並返回不符合喜劇和恐怖標準的電影。 – GarethD 2012-02-15 14:15:41