Interrogazioni SQL

enigmagame
Ciao! Ho qualche dubbio su un'interrogazione SQL.
Dato il seguente schema di base di dati (chavi primarie sottolineate) contenente i dati relativi agli aerei in partenza da un areoporto:
VOLO(CodiceVolo, Compagnia, Destinazione, Data, Ora_partenza);
IMBARCO(Volo, Passeggiero);
PASSEGGERO(Matricola, Cognome, Nome, CittaResidenza, Nazione);
Vincoli di integrità: IMBARCO.Volo -> VOLO, IMBARCO.Passeggero -> PASSEGGERO

Formulare in SQL la seguente interrogazione:
Trovare il codice del volo, la compagnia e la destinazione dei voli del mese di agosto 2002 che avevano imbarcato solo passeggeri italiani.
SELECT v.CodiceVolo, v.Compagnia, v.Destinazione
FROM VOLO v JOIN IMBARCO i ON (v.CodiceVolo = i.Volo)
WHERE v.Data $>=$ 20070801 AND v.Data $<=$ 20070831 AND v.CodiceVolo NOT IN (SELECT i.Volo
                                                                       FROM IMBARCO i JOIN PASSEGGERO p ON (i.Passeggero = p.Matricola)
                                                                       WHERE p.Nazione <> 'Italia')


Il dubbio è questo, nella prima select ho eseguito una join tra VOLO e IMBARCO, questa cosa poteva essere evitata tranquillamente ed avrei potuto utilizzare solamente la tabella VOLO. Ma cosi facendo, oltra ai voli con solo passeggeri italiani, avrei selezionato anche quei voli che non hanno nessuna relazione con imbarco, perchè magari appena inseriti. Ciò che dico è corretto o no?
Grazie!

Risposte
enigmagame
Intanto posto un altro esercizio...
LIBRO(Codice, Titolo, Genere);
SCRIVE(Libro, Autore, Ordine);
SCRITTORE(
Codice, Nome, Cognome, Nazionalita, DataNascita, DataMorte*);
Vincoli di integrità: SCRIVE.Libro -> LIBRO; SCRIVE.Autore -> SCRITTORE

a) Trovare per ogni scrittore il numero di libri che ha scritto insieme ad almeno un altro autore italiano, riportando il cognome, il nome, la nazionalità dello scrittore insieme al conteggio richiesto.

b) Trovare i libri di genere "saggio" per i quali non vi è più nessun autore in vita, riportando il titolo, il genere e le nazionalità degli autori.

c) Trovare il nome e il cognome dello scrittore che ha scritto più libri di tutti gli altri.

Non riesco a venire fuori dalla a, secondo me è banale, ma faccio confusione...
Per quanto riguarda la b (che poi posto) dovrei sempre usare una select annidata o una except, ovvero trovare tutti i libri di genere saggio per cui esiste un autore con campo datamorte diverso da null, e sottrarre questo alla select principale...
Anche sulla c ho dubbi, si può fare questa query senza definire una vista? Tengo a precisare che in questi esercizi le query vanno definite solo dove necessario ovvero solo dove non è possibile raggiungere il risultato in altro modo...
Grazie!

codino75
il MIO problema e' che sono arrugginito con la sintassi sql:
quali parole si possono usare (ad esempio count, max sono disponibili?)?

enigmagame
"codino75":
il MIO problema e' che sono arrugginito con la sintassi sql:
quali parole si possono usare (ad esempio count, max sono disponibili?)?


Certamente, COUNT per contare appunto le occorrenze, e MAX per trovare il valore massimo di un determinato attributo di una tupla rispetto alle altre.
Sicuramente COUNT va usato sia nella a che nella c...

codino75
"enigmagame":
Intanto posto un altro esercizio...
LIBRO(Codice, Titolo, Genere);
SCRIVE(Libro, Autore, Ordine);
SCRITTORE(
Codice, Nome, Cognome, Nazionalita, DataNascita, DataMorte*);
Vincoli di integrità: SCRIVE.Libro -> LIBRO; SCRIVE.Autore -> SCRITTORE

a) Trovare per ogni scrittore il numero di libri che ha scritto insieme ad almeno un altro autore italiano, riportando il cognome, il nome, la nazionalità dello scrittore insieme al conteggio richiesto.


per trovare i libri con accanto il numero di scrittori italiani che lo hanno scritto si puo' fare cosi'?
(alla seguente query bisogna aggiungere il doppio join tra le 3 tabelle, che non ho scritto perche' ne ignoro la sintassi )

select LIBRO.codice, count
from LIBRO, SCRITTORE, SCRIVE
where SCRITTORE.nazionalità='italia'
group by LIBRO.codice

enigmagame
Si, la sintassi esatta è questa:
SELECT l.Codice, Count(*)
FROM LIBRO l JOIN SCRIVE sv ON(l.Codice = sv.Libro) JOIN SCRITTORE st ON(sv.Autore = st.Codice)
WHERE st.Nazionalita='italiana'
GROUP BY l.Codice

In questo modo, per ogni libro scritto, si trova il numero di autori Italiani.

codino75
"enigmagame":
Si, la sintassi esatta è questa:
SELECT l.Codice, Count(*)
FROM LIBRO l JOIN SCRIVE sv ON(l.Codice = sv.Libro) JOIN SCRITTORE st ON(sv.Autore = st.Codice)
WHERE st.Nazionalita='italiana'
GROUP BY l.Codice

In questo modo, per ogni libro scritto, si trova il numero di autori Italiani.


chiamando query1 la query che hai scritto (con l'aggiunta che il numero degli autori deve essere maggiore o uguale a 2), allora si potrebbe forse fare cosi':

select SCRITTORE.nome , count (*)
from SCRITTORE join SCRIVE ....
where SCRIVE.libro IN QUERY1
group by SCRITTORE.nome

spero di non aver detto boiate

enigmagame
"codino75":
chiamando query1 la query che hai scritto (con l'aggiunta che il numero degli autori deve essere maggiore o uguale a 2), allora si potrebbe forse fare cosi':

select SCRITTORE.nome , count (*)
from SCRITTORE join SCRIVE ....
where SCRIVE.libro IN QUERY1
group by SCRITTORE.nome

spero di non aver detto boiate


Dunque devo imporre che il numero degli autori sia maggiore di due, perchè altrimenti potrei includere libri scritti solo da un autore giusto? Per questo si usa la HAVING dopo la GROUP...

Però credo che la query non funzioni, nella tua WHERE confrontiamo SCRIVE.libro, con due valori... ho provato anche a fare una cosa simile ma da errore, precisamente da: Operand should contain 1 column(s)

codino75
"enigmagame":
Si, la sintassi esatta è questa:
SELECT l.Codice, Count(*)
FROM LIBRO l JOIN SCRIVE sv ON(l.Codice = sv.Libro) JOIN SCRITTORE st ON(sv.Autore = st.Codice)
WHERE st.Nazionalita='italiana'
GROUP BY l.Codice

In questo modo, per ogni libro scritto, si trova il numero di autori Italiani.


prova a togliere il count(*) e vediamo cosa ci dice...

enigmagame
"codino75":

prova a togliere il count(*) e vediamo cosa ci dice...


Funziona e fa il conteggio, ma con un'anomalia. Ovvero supponiamo che un libro abbia 4 autori di cui solo 1 italiano. Ai 3 autori stranieri il contatore è pari a 1, giustamente... ma il contatore è pari a 1 anche per l'autore italiano, mentre dovrebbe essere a 0...

codino75
"enigmagame":
[quote="codino75"]
prova a togliere il count(*) e vediamo cosa ci dice...


Funziona e fa il conteggio, ma con un'anomalia. Ovvero supponiamo che un libro abbia 4 autori di cui solo 1 italiano. Ai 3 autori stranieri il contatore è pari a 1, giustamente... ma il contatore è pari a 1 anche per l'autore italiano, mentre dovrebbe essere a 0...[/quote]

c'entrasse qualcosa il fatto che una tupla la tira fuori comunque come nel caso che ha postato con l'immagine gundam, dove tirava fuori righe con NULL anche se il join inteoria non si verificava?
lui mi pare abbia risolto con un right join, ma in queste cose non n ecapisco molto, magari prova ad esplicitare il join manualmente, cioe' scrivendo esplicitamente gli elementi che devono essere uguali

enigmagame
Tralasciando un attimo questa query, prendiamo in mano la terza ovvero:
Trovare il nome il il cognome dello scrittore che ha scritto più libri di tutti gli altri.
Sicuramente è necessario calcolare per ogni autore il numero di libri che ha scritto, non esiste nessun attributo che ce lo dice. (L'attributo ordine della relazione SCRIVE indica la posizione dell'autore nell'elenco degli autori).
SELECT st.Codice, COUNT(*) AS NumeroLibri
FROM SCRITTORE st JOIN SCRIVE sv ON(st.Codice = sv.Autore)
GROUP BY st.Codice

E con questa qui sopra ottengo per ogni autore, il numero di libri scritti... è adesso? Potrei ad esempio ordinare questa per il NumeroLibri (decrescente) usare questa query annidata in un altra e nella principale estrarre il cognome e il nome, ma cosi non funziona, perchè nella SELECT qui sopra non ho un solo campo ma 2...
Che fare?

enigmagame
Però... utilizzando una vista potrei risolvere facilmente, ecco come:
CREATE VIEW ORDINEAUTORI(Nome, Cognome, NLibri) AS
SELECT st.Nome, st.Cognome, COUNT(*)
FROM SCRITTORE st JOIN SCRIVE sv ON(st.Codice = sv.Autore)
GROUP BY st.Nome, st.Cognome

SELECT Nome, Cognome
FROM ORDINEAUTORI
WHERE NLibri = (SELECT MAX(NLibri)
                FROM ORDINEAUTORI)


Ricordo però che il tema precisa di utilizzare le viste SOLO dove necessario, ovvero solamente se non esistono altri metodi...
Che dite? E' possibile in altri modi?

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.