2013-02-21 9 views
5

Mam problem z ustaleniem sposobu na brak wsparcia Oracle dla klauzuli HAVING EVERY.Oracle SQL - czy istnieje standard, który zapewnia KAŻDE obejście problemu?

Mam dwie tabele, produkcja i film, z następującym schematem:

Production (pid, mid) 
Movie(mid, director) 

gdzie „pid” jest liczbą całkowitą reprezentującą identyfikator wydawcy, „średni” jest liczbą całkowitą reprezentującą filmowy identyfikator, a reżyser to jest imię reżysera filmu.

Moim celem jest zdobycie listy wydawców (według ID), którzy publikowali tylko filmy w reżyserii Petera Jacksona lub Bena Afflecka.

W celu osiągnięcia tego, co napisałem następujące zapytanie:

SELECT * 
    FROM Production P, Movie M 
    WHERE P.mid = M.mid; 
    GROUP BY P.pid 
    HAVING EVERY (M.director IN ('Ben Affleck', 'Peter Jackson')); 

Ale ponieważ Oracle nie obsługuje MIEĆ KAŻDY, wszystko mam jest następujący błąd:

HAVING EVERY (M.director IN ('ben affleck', 'PJ')) 
          * 
ERROR at line 5: 
ORA-00907: missing right parenthesis 

Bo reżyserstwo musi odnosić się do każdego filmu wyprodukowanego przez wydawcę, nie sądzę, aby warunek ten mógł zostać przeniesiony do klauzuli WHERE.

Czy istnieje jakiś sposób obejścia tego problemu? Coś, co jest uważane za "standardowe"? Również (i być może ważniejsze), dlaczego Oracle zdecydowało się nie wdrażać KAŻDEGO?

Odpowiedz

4

Spróbuj tego:

SELECT P.pid 
FROM (select distinct Pi.pid, M.Director 
     from Production Pi INNER JOIN 
    Movie M ON Pi.mid = M.mid) P 
GROUP BY P.pid 
HAVING sum(case when P.Director in ('Ben Affleck', 'Peter Jackson') 
      then 1 else 99 end) = 2 

Here is a sqlfiddle demo

+1

To wydaje się rade! Stukrotne dzięki. Kiedy jesteśmy tutaj, czy wiesz, dlaczego firma Oracle nie wdrożyła KAŻDEGO? Czuję, że kod obejścia jest bardzo trudny do odczytania, co jest dla mnie bardzo negatywnym aspektem. – Dan

+1

+1 - Usunąłem moją odpowiedź, ponieważ źle zrozumiałem prośbę PO. Niezła odpowiedź! – sgeddes

3

Po tym myśleć na chwilę, mam wymyślić coś, co jest być może trochę bardziej czytelne niż co ABCade wymyślił:

select distinct P.pid 
    from Production P 
    where P.pid not in (
     -- Get publishers that have produced a movie directed by someone else 
     select P1.pid 
     from Production P1 INNER JOIN Movie M ON P1.mid = M.mid 
     where M.director not in ('Ben Affleck', 'Peter Jackson') 
    ) 

SQLFiddle demo

T Różnica polega na tym, że zamiast szukać producentów mających tylko pożądanych dyrektorów, identyfikujemy wszystkich producentów powiązanych z innymi dyrektorami, a następnie pomijamy ich.

+0

+1 za myślenie nieszablonowe! Jedynym plusem jest skorelowane podkwerendy, które będą kosztować duże zbiory danych. Zobacz moją odpowiedź. – ninesided

+0

+1 to jest znacznie prostsze! –

2

podstawie Dan's own answer, ale usunęliśmy skorelowanej podzapytania, gdyż może wykonać bardzo słabo na dużych zbiorach danych:

SELECT DISTINCT P.pid 
FROM Production P 
LEFT JOIN (
    SELECT P1.pid 
    FROM Production P1 
    INNER JOIN Movie M ON (P1.mid = M.mid) 
    WHERE M.director NOT IN ('Ben Affleck', 'Peter Jackson') 
) V ON (P.pid = V.pid) 
WHERE v.pid IS NULL; 

SQL Fiddle demo