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
codino75
cio' che dici mi sembra corretto.
io per mia chiarezza (ma non so se e' meglio o meno) avrei fatto, se si puo' ,il dopppio join gia' nella clausola from della query principale....

gundamrx91-votailprof
Puoi mettere in join anche la tabella PASSEGGERO, evitando di fa una subselect che e' molto piu' lenta di una join, soprattutto se nella subselect ci fai pure un'altra join!!!

gundamrx91-votailprof
"codino75":
cio' che dici mi sembra corretto.
io per mia chiarezza (ma non so se e' meglio o meno) avrei fatto, se si puo' ,il dopppio join gia' nella clausola from della query principale....


Certo, puoi mettere, oltre alla tabella principale della select, in join tutte le tabelle che vuoi, ovviamente se hanno dei campi di collegamento.
Il vantaggio di questa soluzione deriva dagli indici, che se presenti danno delle perfomance superiori.

enigmagame
"GundamRX91":
Puoi mettere in join anche la tabella PASSEGGERO, evitando di fa una subselect che e' molto piu' lenta di una join, soprattutto se nella subselect ci fai pure un'altra join!!!

Me la puoi scrivere, penso di non aver capito. Grazie!

gundamrx91-votailprof
select v.codicevolo, v.compagnia, v.destinazione from volo v
left join imbarco i on v.codicevolo = i.volo
left join passeggero p on p.matricola = i.passeggero
where (v.data >= 20020801 and v.data <= 20020831) and p.nazione = 'italia'

fatta al volo, ma dovrebbe andare.

enigmagame
"GundamRX91":
select v.codicevolo, v.compagnia, v.destinazione from volo v
left join imbarco i on v.codicevolo = i.volo
left join passeggero p on p.matricola = i.passeggero
where (v.data >= 20020801 and v.data <= 20020831) and p.nazione = 'italia'

fatta al volo, ma dovrebbe andare.


Mmm aspetta, forse faccio confusione io. Ma già con la prima LEFT JOIN vado a considerare voli che magari non hanno nessuna relazione con IMBARCO e questo a me non serve... Cosi non vengono selezionati anche voli che avevano si passeggeri italiani, ma anche altri?
Grazie!

gundamrx91-votailprof
In teoria si, poi il piu' delle volte l'ottimizzatore interno del server sql sistema le cose.
Comunque, come fai giustamente notare, puoi farla cosi':

select v.codicevolo, v.compagnia, v.destinazione from volo v
left join imbarco i on v.codicevolo = i.volo
left join passeggero p on p.matricola = i.passeggero and p.nazione = 'italia'
where (v.data >= 20020801 and v.data <= 20020831)

e dovrebbe funzionare come la precedente.

codino75
"GundamRX91":
In teoria si, poi il piu' delle volte l'ottimizzatore interno del server sql sistema le cose.
Comunque, come fai giustamente notare, puoi farla cosi':

select v.codicevolo, v.compagnia, v.destinazione from volo v
left join imbarco i on v.codicevolo = i.volo
left join passeggero p on p.matricola = i.passeggero and p.nazione = 'italia'
where (v.data >= 20020801 and v.data <= 20020831)

e dovrebbe funzionare come la precedente.


mi sembra che questa peschi tutti i voli in cui ci sia almeno 1 italiano, e non i voli in cui tutti i passeggeri sono italiani.

gundamrx91-votailprof
Perche'?

Questa query dovrebbe, il condizionale e' d'obbligo :D, estrarre:

1) tutti i voli che rientrano nel range di data indicato
2) tutti gli imbarchi associati ai voli del punto 1)
3) tutti i passeggeri prsenti negli imbarchi del punto 2) di nazionalita' italiana

comunque ora che ci penso, nella precendente query che ho indicato, vengono estratti solo i passeggeri italiani, perche' anche se la join non restringe il campo di selezione dei record, la where invece lo fa.

gundamrx91-votailprof
Comunque la soluzione piu' corretta e' speficare la nazionalita' nella clausola where, altrimenti estrae dei record con dei valori null.

codino75
"GundamRX91":
Perche'?

Questa query dovrebbe, il condizionale e' d'obbligo :D, estrarre:

1) tutti i voli che rientrano nel range di data indicato
2) tutti gli imbarchi associati ai voli del punto 1)
3) tutti i passeggeri prsenti negli imbarchi del punto 2) di nazionalita' italiana

comunque ora che ci penso, nella precendente query che ho indicato, vengono estratti solo i passeggeri italiani, perche' anche se la join non restringe il campo di selezione dei record, la where invece lo fa.


ripropongo la mia obiezione....
a me sembra che la tua query estraga tutti i voli di agosto in cui ci sia almeno un passeggero italiano... ma non e' quello che chiede il testo del problema

enigmagame
"codino75":

ripropongo la mia obiezione....
a me sembra che la tua query estraga tutti i voli di agosto in cui ci sia almeno un passeggero italiano... ma non e' quello che chiede il testo del problema

Concordo con te, qui vengono estratti i voli in cui sono presenti passeggeri italiani, ma dentro ci sono anche voli in cui i passeggeri sono si italiani e di altre nazionalità.
Per come la vedo io le soluzioni a questo problema sono due, o quella proposta da me all'inizio del post (due select), oppure l'uso della EXCEPT...

gundamrx91-votailprof
Miscredenti :D

Allora, allego 4 immagini:
la prima e' l'estrazione dei soli passeggeri italiani dal volo 1;
la seconda e' l'estrazione dei soli passeggeri americani dal volo 1;
la terza e' l'estrazione dei soli passeggeri italiani, indicando pero' nella join la condizione di estrazione 'italia'; in questo caso come si vede vengono estratte piu' righe di quelle necessarie, anche se comunque le colonne utili sono giuste (lascio a voi scoprire perche' ;) );
la quarta e' l'estrazione dei soli passeggeri italiani, con la modalita' precedente, con una piccola ma significativa modifica della query....








codino75
per gundam:
prova a rileggere il primo post, dove c'e' il quesito.
si chiede di trovare i voli di agosto dove sono state imbarcati SOLO passegeri italiani, mentre la tua query restituisce il volo 1 in cui sono imbarcati italiani , uno statunitense e un indiano....
saluti
alex

gundamrx91-votailprof
"codino75":
per gundam:
prova a rileggere il primo post, dove c'e' il quesito.
si chiede di trovare i voli di agosto dove sono state imbarcati SOLO passegeri italiani, mentre la tua query restituisce il volo 1 in cui sono imbarcati italiani , uno statunitense e un indiano....
saluti
alex


Scusa, ma mi dici esattamente dove vedi, nelle query allegate, un volo con i passeggeri da te indicati?
Il fatto che abbia estratto un solo volo e' perche' ho popolato le tabelle in quel modo, quindi solo per comodita', altrimenti, avrebbe estratto piu' voli....

gundamrx91-votailprof
Forse non sono ben chiare le immagini allegate:
sulla sinistra, una sotto l'altra, ci sono le tre tabelle, nude e crude, aperte con i soli record che le popolano; la finestra che c'e' sulla destra e' la query (e relative varianti), con sotto il risultato della stessa.

codino75
per gundam:
il problema NON chiedeva di trovare gli IMBARCHI degli italiani in agosto,
ma il codice dei VOLI di agosto in cui fossero imbarcati SOLO italiani.
la tua query restituisce il volo 1 in cui sono imbarcati anche non italiani.
saluti
alex

gundamrx91-votailprof
scusate ragazzi, ho preso una cantonata veramente grossa: in effetti leggendo attentamente la richiesta si vuole estrarre i voli con SOLO (ora capisco il maiuscolo di Codino :D) passeggeri italiani:

select codice_vol,compagnia_vol,codice_pass_imb from voli
left join imbarchi on codice_volo_imb = codice_vol
where data_vol >= '01/01/2007' and data_vol <= '31/12/2007'
and codice_vol not in (select codice_volo_imb from imbarchi left join passeggeri on
codice_pas = codice_pass_imb where nazione_pas <> 'italia')

che e' la query indicata da enigmagame.

Scusate ancora :p

gundamrx91-votailprof
giusto per correttezza ho aggiuto un record in piu', negli imbarchi, di un passeggero italiano relativo ad un nuovo volo (nuovo record nella tabella voli); ovviamente la query estrae solo quel volo, quindi per avere quelli di agosto bisognera' cambiare le date di estrazione........

mannaggia alla vecchiaia :p

enigmagame
"GundamRX91":
scusate ragazzi, ho preso una cantonata veramente grossa: in effetti leggendo attentamente la richiesta si vuole estrarre i voli con SOLO (ora capisco il maiuscolo di Codino :D) passeggeri italiani:

select codice_vol,compagnia_vol,codice_pass_imb from voli
left join imbarchi on codice_volo_imb = codice_vol
where data_vol >= '01/01/2007' and data_vol <= '31/12/2007'
and codice_vol not in (select codice_volo_imb from imbarchi left join passeggeri on
codice_pas = codice_pass_imb where nazione_pas <> 'italia')

che e' la query indicata da enigmagame.

Scusate ancora :p


No problema! :D

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