# Filmografie
Si consideri il seguente schema:
- Regista(**Nome**, DataNascita, Nazionalità)
- Attore(**Nome**, DataNascita, Nazionalità)
- Interpreta(**Attore**, **Film**, **Personaggio**)
- Film(**Titolo**, NomeRegista, Anno)
- Proiezione(**NomeCin**, **CittaCin**, **TitoloFilm**)
- Cinema(**Citta**, **NomeCinema**, Sale, Posti)
---
**Domanda 1.** Selezionare le Nazionalità dei registi che hanno diretto qualche film nel 1992, ma non hanno diretto nessun film nel 1993.
```sql=
-- Soluzione 1
select distinct Nazionalità
from Regista
where Nome in (
select NomeRegista
from Film
where Anno = '1992')
and
Nome not in (
select NomeRegista
from Film
where Anno = '1993');
-- Soluzione 2
select distinct Nazionalità
from Regista R join Film F
on R.Nome = F.NomeRegista
where F.anno = '1992'
and
(select count(*)
from Film
where Anno = '1993'
and NomeRegista = R.Nome) = 0;
-- Soluzione 3
select distinct Nazionalità
from Regista, Film
where Nome = NomeRegista and Anno = '1992'
and Nome not in (
select NomeRegista
from Film
where Anno = '1993'
);
```
Versione con **ERRORE**!
```sql=
-- Soluzione SBAGLIATA
SELECT Nazionalità
FROM Regista JOIN Film
ON Nome = NomeRegista
WHERE Anno = 1992 AND Anno <> 1993
```
La clausola `where` agisce a livello di tupla.
---
**Domanda 2.** Nomi dei registi che nel 1993 hanno diretto più film che nel 1992.
```sql=
-- Soluzione 1
select Nome
from Regista R
where (
select count(*)
from Film
where NomeRegista = R.Nome and Anno = '1993')
> (
select count(*)
from Film
where NomeRegista = R.Nome and Anno = '1992');
-- Soluzione 2
select distinct NomeRegista
from Film F1
where Anno = '1993'
group by NomeRegista
having count(*) > (
select count(*)
from Film F2
where Anno = '1992'
and F1.NomeRegista = F2.NomeRegista);
-- Soluzione 3 (con vista)
create view NumPerAnno(Nom, Ann, Num) as
select NomeRegista, Anno, count(*)
from Film
group by NomeRegista, Anno
select Nom as NomeRegistaCercato
from NumPerAnno N1
where Ann = '1993' and
Nom not in (
select Nom
from NumPerAnno N2
where N2.Ann = '1992' and N1.Num <= N2.Num);
```
Versione con **ERRORE**!
```sql=
-- Soluzione 2 SBAGLIATA
-- Si perdono quelli che non hanno fatto
-- film nel 1992
select distinct NomeRegista
from Film F1
where Anno = '1992'
group by NomeRegista
having count(*) < (
select count(*)
from Film F2
where Anno = '1993'
and F1.NomeRegista = F2.NomeRegista);
```
---
**Domanda 3.** Date di nascita dei registi che hanno diretto film in proiezione sia a Torino che a Milano.
```sql=
-- Soluzione 1
select distinct NomeRegista, DataNascita
from Regista join Film on Nome = NomeRegista
where Titolo in (
select TitoloFilm
from Proiezione
where CittaCin = 'Torino')
and Titolo in (
select TitoloFilm
from Proiezione
where CittaCin = 'Milano');
-- Soluzione 2
select distinct NomeRegista, DataNascita
from Regista R join Film F on R.Nome = F.NomeRegista
join Proiezione P on F.Titolo = P.TitoloFilm
where CittaCin = 'Milano'
and Titolo in (
select TitoloFilm
from Proiezione
where CittaCin = 'Torino');
-- Soluzione 3
select distinct Nome, DataNascita
from Regista R join Film F on R.Nome = F.NomeRegista
join Proiezione P1 on P1.TitoloFilm = F.titolo
join Proiezione P2 on P2.TitoloFilm = F.titolo
where P1.Citta = 'Torino' and P2.Citta = 'Roma';
```
Versioni con **ERRORI**!
```sql=
-- Soluzione SBAGLIATA 1
-- non può mai esistere una tupla con entrambi
-- i valori
select distinct NomeRegista, dataNascita
from Regista join Film on Nome = NomeRegista
where Titolo in (
select TitoloFilm
from Proiezione
where CittaCin = 'Milano'
and CittaCin = 'Torino');
-- Soluzione SBAGLIATA 2
-- si considerano i film che soddisfano
-- OR logico, quindi non va bene
select distinct NomeRegista, dataNascita
from Regista join Film on Nome = NomeRegista
where Titolo in (
select TitoloFilm
from Proiezione
where CittaCin = 'Milano'
or CittaCin = 'Torino');
```
---
**Domanda 4.** Film proiettato nel maggior numero di cinema a Milano.
```sql=
-- Soluzione 1
select TitoloFilm
from Proiezione
where CittaCin = 'Milano'
group by TitoloFilm
having count(distinct NomeCinema) >= all (
select count(*)
from Proiezione
where CittaCin = 'Milano'
group by TitoloFilm);
-- Soluzione 2
create view ProiezMilano(Titolo, Num) as
select TitoloFilm, count(*)
from Proiezione
where CittaCin = 'Milano'
group by TitoloFilm
select Titolo
from ProiezMilano
where Num = (
select max(Num)
from ProiezMilano);
```
---
**Domanda 5.** Attori che hanno interpretato più di un ruolo nello stesso film.
```sql=
-- Soluzione 1.1
select distinct Attore
from Interpreta I1 join Interpreta I2
on I1.Attore = I2.Attore and I1.Film = I2.Film
where I1.Personaggio <> I2.Personaggio;
-- Soluzione 1.2
select distinct I1.Attore
from Interpreta I1, Interpreta I2
where I1.Attore = I2.Attore
and I1.Film = I2.Film
and I1.Personaggio <> I2.Personaggio;
-- Soluzione 2.1
-- funziona per com'è fatta la chiave
-- e per via del fatto che raggruppiamo per
-- attore e personaggio
select distinct Attore
from Interpreta
group by Attore, Film
having count(Personaggio) > 1;
-- Soluzione 2.2
select distinct Attore
from Interpreta
group by Attore, Film
having count(distinct Personaggio) > 1;
-- Soluzione 2.3
-- funziona per com'è fatta la chiave
-- e per via del fatto che raggruppiamo per
-- attore e personaggio
select distinct Attore
from Interpreta
group by Attore, Film
having count(*) > 1;
```
---
**Domanda 6.** Selezionare i film in cui recita un solo attore che però interpreta più personaggi.
```sql=
-- Soluzione 1.1
select Film
from Interpreta
group by Film
having count(distinct Attore) = 1
and count(distinct Personaggio) > 1;
-- Soluzione 1.2
-- sempre per il fatto della chiave
select Film
from Interpreta
group by Film
having count(distinct Attore) = 1
and count(*) > 1;
```
---
**Domanda 7.** Trovare gli attori italiani che non hanno mai recitato con altri attori italiani.
```sql=
-- Soluzione 1
-- La subquery identifica gli attori (in generale, anche
-- non italiani) che hanno recitato con altri attori italiani
SELECT A1.Nome
FROM Attore A1
WHERE A1.Nazionalità = 'Italiana'
AND A1.Nome NOT IN (
SELECT DISTINCT I1.Attore
FROM Interpreta I1
JOIN Interpreta I2 ON I1.Titolo = I2.Titolo
JOIN Attore A2 ON I2.Attore = A2.Nome
WHERE A2.Nazionalità = 'Italiana'
AND I1.Attore <> A2.Nome
);
-- Soluzione 2
-- Subquery funziona per ogni riga, quindi restituisce l'attore stesso
-- se ha collaborato con altri italiani, oppure nulla
SELECT Nome
FROM Attore A1
WHERE Nazionalità = 'Italiana'
AND A1.Nome NOT IN (
SELECT I1.Attore
FROM Interpreta I1, Interpreta I2, Attore A2
WHERE I1.Titolo = I2.Titolo
AND I2.Attore = A2.Nome
AND A1.Nome = I1.Attore -- Correlazione esplicita
AND A2.Nome <> A1.Nome
AND A2.Nazionalità = 'Italiana'
);
-- Soluzione 3
create view IntIta as
select Film, Attore
from Interpreta
where Attore in (
select Nome
from Attore
where Nazionalità = 'Italiana');
select Attore
from IntIta
where Attore not in (
select X.Attore
from IntIta X, IntIta Y
where X.Film = Y.Film
and X.Attore <> Y.Attore);
```
---
**Domanda 8.** Trovare i film di registi italiani dove non recita nessun italiano.
```sql=
select Titolo
from Regista join Film on Nome = NomeRegista
where Nazionalità = 'Italiana'
and Titolo not in (
select Film
from Interpreta join Attore on Attore = Nome
where Nazionalità = 'Italiana'
);
```
---
**Domanda 9.** Registi che hanno recitato in almeno un loro film.
```sql=
SELECT DISTINCT NomeRegista
FROM Film JOIN Interpreta
ON Film.Titolo = Interpreta.Film
WHERE Interpreta.Attore = Film.NomeRegista;
```
---
**Domanda 10.** I registi che hanno recitato in almeno 4 loro film interpretandovi un totale di almeno 5 personaggi diversi (non si consideri il caso in cui un regista/attore interpreta personaggi diversi che però hanno lo stesso nome, in film diversi)
```sql=
select NomeRegista
from Film join Interpreta on Titolo = Film
where NomeRegista = Attore
group by NomeRegista
having count(distinct Titolo) >= 4
and count(distinct Personaggio) >= 5
```