2013-02-21 17 views
5

Non riesco a trovare un modo per aggirare la mancanza di supporto di Oracle per la clausola HAVING EVERY.Oracle SQL: esiste una soluzione standard HAVING EVERY?

ho due tabelle, di produzione e di film, con il seguente schema:

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

dove 'pid' è in numero intero che rappresenta ID publisher, 'metà' è un numero intero che rappresenta ID di film, e il regista è il nome del regista del film.

Il mio obiettivo è ottenere un elenco di editori (per ID) che hanno pubblicato solo film diretti da Peter Jackson o Ben Affleck.

Al fine di raggiungere questo obiettivo, avevo scritto la seguente query:

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

Ma dal momento che Oracle non supporta avere ogni, tutto quello che ottiene è il seguente errore:

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

Perché la direzione deve applicarsi a tutti i film prodotti dall'editore, non credo che la condizione possa essere spostata nella clausola WHERE.

C'è qualche modo per aggirare questo posto di blocco? Qualcosa che è considerato "standard"? Inoltre (e forse ancora più importante) perché Oracle ha scelto di non implementare HAVING OGNI?

risposta

4

Prova questo:

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

che sembra fare il trucco! Grazie mille. Mentre siamo qui, sai perché Oracle non ha implementato AVENDO OGNI? Mi sento come se il codice di soluzione fosse molto hacky/difficile da leggere, il che per me è un aspetto molto negativo. – Dan

+1

+1 - Ho cancellato la mia risposta in quanto ho frainteso la richiesta di OPs. Bella risposta! – sgeddes

3

Dopo averci pensato per un po ', mi è venuta in mente qualcosa che è forse un po' più leggibile di quello che ABCade si avvicinò con:

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 La differenza è che, piuttosto che cercare produttori con i soli direttori desiderati, identifichiamo tutti i produttori collegati ad altri registi e poi li omettiamo.

+0

+1 per pensare fuori dagli schemi! Solo il downer è la sottoquery correlata che diventerà costosa su dataset di grandi dimensioni. Vedi la mia risposta. – ninesided

+0

+1 questo è molto più semplice! –

2

sulla base di Dan's own answer, ma ho rimosso il subquery correlata, in quanto sarebbe probabile eseguire molto male in grandi serie di dati:

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