Query con attributi uguali a NULL

di zio_mangrovia il
22 risposte
Un esercizio sulla scrittura di una query dice:

Indicare matricola e cognome degli studenti il cui percorso di studi è durato (o dura da) oltre sei anni

La soluzione:
SELECT Matricola,
       Cognome
FROM studente
WHERE (DataLaurea IS NULL
       AND DataIscrizione + INTERVAL 6 YEAR < current_date())
    OR (DataIscrizione + INTERVAL 6 YEAR < DataLaurea);
Mi chiedo perchè nella seconda preposizione dell'operatore OR non si è verificato anche che DataLaurea fosse diverso da NULL?
Cioè io avrei scritto:
OR ( DataLaurea IS NOT NULL
       AND DataIscrizione + INTERVAL 6 YEAR < DataLaurea)
     );
Mi chiedo cosa accada quando si legge un record il cui attributo DataLaurea è NULL e lo si confronti con DataIscrizione + INTERVAL 6 YEAR

22 Risposte

  • E' una bella domanda.
    Sai cosa significa NULL?
  • Significa che il valore dell'attributo è sconosciuto, indeterminato ma è definito.
    Ma se avessi scritto la query avrei previsto questo controllo, cosa ne pensi? Sbaglio?
  • zio_mangrovia ha scritto:


    Significa che il valore dell'attributo è sconosciuto, indeterminato ma è definito.
    Ma se avessi scritto la query avrei previsto questo controllo, cosa ne pensi? Sbaglio?
    Quindi pensi di poter confrontare un dato NULL con un dato non-NULL?

    Cioè ad esempio confrontare il saldo del mio conto corrente (che non conosci, diciamo NULL) col tuo (che invece conosci)?
    Sono uguali? diversi? maggiore, minore?

    Rifletti un attimo (è classico non aver ben presente come funziona NULL e magari non conoscere coalesce)
  • No, secondo me non ha senso confrontare il valore (p.e. numerico) di un attributo con NULL in quanto non rappresenta, passatemi il termine, alcun valore "discreto".
    Perdonate la domanda banale ma sto imparando da poco SQL... non so quanto sia intelligente il linguaggio quindi ecco perchè a scanso di equivoci nella query avrei aggiunto un controllo in più ma non ho ancora capito se il mio controllo aggiuntivo è giusto o sbagliato (cioè avrei verificato che il valore fosse diverso da NULL).
    Azzardo l'ipotesi! Forse SQL è talmente intelligente che nel caso in cui si confronta un valore di un attributo con NULL ignora il record e va oltre perchè non avrebbe senso?
    Grazie
  • zio_mangrovia ha scritto:


    ...
    Azzardo l'ipotesi! Forse SQL è talmente intelligente che nel caso in cui si confronta un valore di un attributo con NULL ignora il record e va oltre perchè non avrebbe senso?
    Grazie
    No,
    di regola , per venire incontro al senso comune ma contro la logica del suo significato, il NULL
    viene ignorato solo nelle funzioni di aggregazione ( per es. SUM)

    Prova ad eseguire una query di questo tipo :

    select * from dbo.tab1 where c1 not in (select c1 from tab2)

    inserendo o togliendo in tab2 un solo record con c1=NULL
  • Ho provato, se inserisco anche un solo NULL il risultato della query è zero record.
    Se non ne inserisco nemmeno uno ho il risultato atteso, quindi dovrei concludere che l'esistenza di un attributo NULL manda a monte il lavoro della prima select ?
  • zio_mangrovia ha scritto:


    Ho provato, se inserisco anche un solo NULL il risultato della query è zero record.
    Se non ne inserisco nemmeno uno ho il risultato atteso, quindi dovrei concludere che l'esistenza di un attributo NULL manda a monte il lavoro della prima select ?
    E' tutto perfettemente logico e spiegabile;
    basta fare mente locale sulle tabelle di verità
    e ricompilarle aggiungendo a TRUE e FALSE anche NULL il cui significato , come già detto, è "Valore sconosciuto"
  • Capisco ciò che vuoi dire ma non riesco ad afferrare il concetto di come sia applicabile, provo alla luce dei tuoi chiarimenti, a ragionare sul mio quesito iniziale cioè sull'interpretazione del seguente pezzo di codice:
    OR (DataIscrizione + INTERVAL 6 YEAR < DataLaurea);
    operatore logico OR: se uno dei suoi operandi o entrambi sono 1 allora il risultato è 1.
    Se introduco nella tabella dell'operatore OR il NULL cosa ottengo?

    true OR false =
    true OR true =
    true OR null =
    false OR false =
    false OR true =
    false OR null =
    null OR false =
    null OR true =
    null OR null =

    non capisco come devo trattare questo nuovo valore, lo zero è il false e l'uno il true ma come si combinano per null e true ?!?! cosa ottengo?
    Se avessi '2016-02-02' < NULL questa logica cosa mi restituisce?
  • E' molto più semplice di come sembri: NULL confrontato qualsiasi cosa = NULL.
    C'è un operatore specifico, is null (/ is not null)

    Quindi non hai solo 2 valori di risultato di un confronto (true, false), bensì 3 (true, false, null)
  • SELECT Matricola, Cognome FROM studente
    WHERE (DataLaurea IS NULL AND DataIscrizione + INTERVAL 6 YEAR < current_date())
    OR (DataLaurea IS NOT NULL AND DataIscrizione + INTERVAL 6 YEAR < DataLaurea)

    Così deve funzionare.

  • ...
    non capisco come devo trattare questo nuovo valore, lo zero è il false e l'uno il true ma come si combinano per null e true ?!?! cosa ottengo?
    True or null=true
    False or null =null

    True and null =null
    False and null=false
  • Ora capisco la logica di questa porzione di codice
    select * from dbo.tab1 where c1 not in (select c1 from tab2)
    Se la seconda select restituisce una serie di valori tra cui compare anche un solo NULL (valore sconosciuto), il where specifica tutto ciò che non è contenuto nel risultato della select precedente per cui il risultato è per forza NULL in quanto indeterminato.

    In questo caso invece:
    SELECT Matricola, Cognome FROM studente
    WHERE (DataLaurea IS NULL AND DataIscrizione + INTERVAL 6 YEAR < current_date()) 
    OR (DataIscrizione + INTERVAL 6 YEAR < DataLaurea)
    Se il valore dell'attributo DataLaurea di un record contiene NULL il risultato della disuguaglianza è NULL per cui mi ritrovo peril singolo record la seguente condizione:
    (DataLaurea IS NULL AND DataIscrizione + INTERVAL 6 YEAR < current_date()) 
    OR NULL
    per cui vengono ricercati solo i ricordi che soddisfano la prima condizione?
  • Biagio De Franco ha scritto:


    SELECT Matricola, Cognome FROM studente
    WHERE (DataLaurea IS NULL AND DataIscrizione + INTERVAL 6 YEAR < current_date())
    OR (DataLaurea IS NOT NULL AND DataIscrizione + INTERVAL 6 YEAR < DataLaurea)

    Così deve funzionare.
    Quello che dici è vero, ma a mio avviso è interessante e necessario capire la logica che applica SQL nelle condizioni con gli operatori logici dove coinvolto il valore NULL. E' da porre l'attenzione sui ragionamenti che evidenzia @sspintux
  • zio_mangrovia ha scritto:


    Biagio De Franco ha scritto:


    SELECT Matricola, Cognome FROM studente
    WHERE (DataLaurea IS NULL AND DataIscrizione + INTERVAL 6 YEAR < current_date())
    OR (DataLaurea IS NOT NULL AND DataIscrizione + INTERVAL 6 YEAR < DataLaurea)

    Così deve funzionare.
    Quello che dici è vero, ma a mio avviso è interessante e necessario capire la logica che applica SQL nelle condizioni con gli operatori logici dove coinvolto il valore NULL. E' da porre l'attenzione sui ragionamenti che evidenzia @sspintux
    Non c'è molto da capire, l'ho già scritto sopra.
    Non bisogna farsi "fregare" da mysql che indica NULL come falso.
    Provare per credere
    
    SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL;
Devi accedere o registrarti per scrivere nel forum
22 risposte