Interrogazioni SQL
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.
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!
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
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....
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....
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!!!
"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.
"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!
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.
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.
"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!
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.
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.
"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.
Perche'?
Questa query dovrebbe, il condizionale e' d'obbligo
, 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.
Questa query dovrebbe, il condizionale e' d'obbligo

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.
Comunque la soluzione piu' corretta e' speficare la nazionalita' nella clausola where, altrimenti estrae dei record con dei valori null.
"GundamRX91":
Perche'?
Questa query dovrebbe, il condizionale e' d'obbligo, 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
"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...
Miscredenti 
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....




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....




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
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
"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....
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.
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.
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
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
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
) 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

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
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
mannaggia alla vecchiaia :p
"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) 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!
