2013-08-02 3 views
0

У меня возникли проблемы с моим тегом или тегом базы данных моей маленькой пленки.Выберите несколько категорий фильмов

Моя таблица:

ID(index),Name(film name),category 

Один фильм может иметь несколько категорий.

SELECT Name FROM categorytable WHERE category ='Action'; 

работает нормально, но если я хочу другие теги я получаю пустой указатель:

SELECT Name FROM categorytable WHERE category ='Action' AND category ='Sci-Fi'; 

Пример выбора:

1 Film001  Action 
2 Film001  Sci-Fi 
3 Film002  Action 

EDIT: Мой дом databese:

ID|NAMEFILM|DESCRIPTION 

И полный запрос:

SELECT DATABASEFILM.NAMEFILM , DATABASEFILM.DESCRIPTION , NAME from DATABASEFILM , CATEGORY where DATABASEFILM.NAMEFILM=NAME AND category=(SELECT NAME FROM CATEGORY WHERE category ='Action'); 
+1

Вы попробовали 'ИЛИ'? 'SELECT Name FROM categorytable WHERE category = 'Action' OR category = 'Sci-Fi''; – Jack

+1

'WHERE category IN ('Action', 'Sci-Fi');' –

+0

Когда я использую OR query works, но нахожу все фильмы «Action», но не обязательно «Sci-Fi». – Shu

ответ

3

Причина, по которой ваш запрос не работает, состоит в том, что каждая строка имеет только одну категорию. Вместо этого вам нужно выполнить агрегацию. Я предпочитаю делать условия в предложении having, потому что это общий подход.

SELECT Name 
FROM categorytable 
group by Name 
having sum(case when category ='Action' then 1 else 0 end) > 0 and 
     sum(case when category ='Sci-Fi' then 1 else 0 end) > 0; 

Каждый пункт в having тестирует наличие одной категории. Если, например, вы изменили этот вопрос, чтобы быть «боевики, которые не Sci-Fi», то вы бы изменить положение having, сделав второе условие, равное 0:

having sum(case when category ='Action' then 1 else 0 end) > 0 and 
     sum(case when category ='Sci-Fi' then 1 else 0 end) = 0; 
+1

Это неправильно. Если вы группируете по категориям, вы получаете одну строку для каждой категории. Ни одна строка вашего сгруппированного результата не может получить положительный счет для сопоставления двух разных категорий, поскольку строки, вносящие вклад в строку результатов, имеют одну и ту же категорию. Думаю, ты собирался сгруппировать по имени. –

+0

@SteveKass. , , Хороший улов. Это должно быть 'group by Name ', как вы предлагаете. –

1

Вы можете использовать или пункт, или если у вас есть несколько категорий, вероятно, будет проще в использовании

Так что либо

SELECT Name FROM categorytable WHERE category ='Action' OR category ='Sci-Fi' 

Или с помощью IN

SELECT Name 
FROM categorytable 
WHERE category IN ('Action', 'Sci-Fi', 'SomeOtherCategory ') 

Использование IN должно составлять то же самое, но его легче читать, если вы t добавляя более двух категорий.

+0

Но что, если я хочу примеры фильмов, которые являются «Action» и «Sci-Fi» не только «Action»? – Shu

0
with mustAppear(category) as (
    select 'Action' 
    union all 
    select 'Sci-Fi' 
) 
    select Name -- select those film names for which 
    from categorytable as C1 
    where not exists (-- there is no category that must appear with that name 
    select M.category 
    from mustAppear as M 
    where not exists (-- that does not. 
     select * 
     from categorytable as C2 
     where C2.Name = C1.Name 
     and C2.category = M.category 
    ) 
) 

вы также можете быть более прямой таким образом:

select Name 
from categorytable 
where category = 'Sci-Fi' 
intersect 
select Name 
from categorytable 
where category = 'Action'; 

преимуществом бывшего запроса является то, что вы можете использовать его без изменений при создании постоянной таблицы (mustAppear, или вы можете использовать таблицу переменной @mustAppear) в удерживать категорию который должен совпадать. Последний запрос проще, но он должен быть переписан при изменении категорий.

+0

Первый запрос не работает в SQLite. –

+0

Извините, я пропустил тег sqlite, но если у вас есть постоянная таблица под названием MustAppear с требуемыми категориями, вам не понадобится предложение WITH и не должно быть проблем с использованием тела первого запроса. –