Padri, Madri & Figli

Soluzioni:
  1. Le persone che guadagnano più dei rispettivi padri, mostrando nome, reddito e reddito del padre:

    Per chiarire, prima elenco tutto dei padri e dei figli:

    select f.nome,f.eta,f.reddito, p.nome,p.eta,p.reddito from persone p,persone f,paternita where p.nome=padre and f.nome=figlio
    


    Poi è sufficiente aggiungere la condizione sul reddito:
    select f.nome,f.eta,f.reddito, p.nome,p.eta,p.reddito from persone p,persone f,paternita where p.nome=padre and f.nome=figlio and  f.reddito>p.reddito
    

  2. Massimo dei redditi per ogni gruppo di persone che sono maggiorenni ed hanno la stessa età (indicando anche l’età).

    Per chiarezza trovo prima tutti i dati di quelli che hanno la stessa età (ma non sono loro stessi):

    select a.nome,a.eta,a.reddito,b.nome,b.eta,b.reddito  from persone a, persone b where  a.eta=b.eta and a.nome<>b.nome
    


    Poi raggruppo per età, togliendo i nomi, che producono troppe righe:
    SELECT a.eta, max(a.reddito) AS ["reddito massimo"] FROM persone AS a, persone AS b
    WHERE a.eta=b.eta and a.nome<>b.nome and a.eta>18 GROUP BY a.eta;
    

  3. I padri i cui figli sotto i 30 anni hanno un reddito medio maggiore di 20.

    Come per l’es.1, per chiarire, prima elenco tutto dei padri e dei figli:

    select f.nome,f.eta,f.reddito, p.nome,p.eta,p.reddito from persone p,persone f,paternita where p.nome=padre and f.nome=figlio
    
    poi aggiungo la condizione sull’età:
    select f.nome,f.eta,f.reddito, p.nome,p.eta,p.reddito from persone p,persone f,paternita where p.nome=padre and f.nome=figlio and f.eta<30
    


    Per trovare il reddito medio devo raggruppare sul nome del padre (e togliere le colonne dei nomi e delle età, che producono troppe righe)
    SELECT AVG( f.reddito) as reddito_medio FROM persone AS p, persone AS f, paternita
    WHERE p.nome=padre and f.nome=figlio and f.eta<30 GROUP BY p.nome
    


    A questo punto però non posso mettere la condizione AVG(f.reddito)>20, quindi faccio due select:
    SELECT * FROM (SELECT AVG(f.reddito) AS reddito_medio FROM persone AS p, persone AS f, paternita
    WHERE p.nome=padre and f.nome=figlio and f.eta>30 GROUP BY p.nome) WHERE reddito_medio>20;
    

  4. Nome ed età delle madri che hanno almeno un figlio minorenne.

    Trovo madri e figli come prima (ordino per nome per migliore controllo)

    SELECT  m.nome, m.eta, m.reddito,f.nome, f.eta, f.reddito FROM persone AS m, persone AS f, maternita
    WHERE m.nome=madre And f.nome=figlio ORDER BY m.nome
    


    Aggiungo la condizione sull’età, ma non cambia nulla (nessun minorenne)
    SELECT  m.nome, m.eta, m.reddito,f.nome, f.eta, f.reddito FROM persone AS m, persone AS f, maternita
    WHERE m.nome=madre And f.nome=figlio and f.eta>21
    
    Per esprimere la condizione ‘almeno 1 figlio’ cioè avere i nomi delle madri una sola volta e non una volta per ogni figlio, tolgo i nomi dei figli e metto distinct:
    SELECT distinct  m.nome, m.eta, m.reddito FROM persone AS m, persone AS f, maternita
    WHERE m.nome=madre And f.nome=figlio and f.eta>21
    
    Vengono tutte le madri, perché non ci sono figli minorenni:


    Per controllo, cerco le madri che hanno almeno un figlio con più di 30 anni:
    SELECT distinct  m.nome, m.eta, m.reddito FROM persone AS m, persone AS f, maternita
    WHERE m.nome=madre And f.nome=figlio and f.eta>30
    


    Per eseguire come rchiesto con un join per selezionare nome ed età delle madri, ed una sottointerrogazione per la condizione sui figli minorenni.

    SELECT m.nome, m.eta, m.reddito, f.nome, f.eta, f.reddito
    FROM persone AS m, [SELECT * from persone where eta>21]. AS f, maternita
    WHERE m.nome=madre And f.nome=figlio
    
    Che dà madri e figli, e infine tolgo i dati dei figli e metto distinct:
    SELECT distinct  m.nome, m.eta, m.reddito
    FROM persone AS m, [SELECT * from persone where eta>21]. AS f, maternita
    WHERE m.nome=madre And f.nome=figlio
    ORDER BY m.nome;
    


    Per eseguire come richiesto con due sottointerrogazioni e nessun join.

    SELECT * FROM maternita WHERE figlio IN (SELECT nome from persone where eta>21)
    
    E, per avere le medri solo una volta,
    SELECT DISTINCT madre FROM maternita WHERE figlio IN (SELECT nome from persone where eta>21)
    


  5. Nome ed età delle madri che hanno almeno un figlio la cui età differisce meno di 20 anni dalla loro.

    Prima elenco le differenze di età:

    SELECT m.nome, m.eta, f.nome, f.eta, m.eta-f.eta as differenza FROM persone AS m, persone AS f, maternita
    WHERE m.nome=madre And f.nome=figlio
    


    Vedo che non ci sono madri con differenza<20, quindi metterò 21 per vedere qualcosa

    SELECT m.nome, m.eta, f.nome, f.eta, m.eta-f.eta as differenza FROM persone AS m, persone AS f, maternita
    WHERE m.nome=madre And f.nome=figlio and m.eta-f.eta>21
    


    In questo caso i nomi delle madri sono unici, ma per essere sicuri occorre togliere i dati dei figli e mettere DISTINCT

    SELECT DISTINCT  m.nome, m.eta FROM persone AS m, persone AS f, maternita
    WHERE m.nome=madre And f.nome=figlio and m.eta-f.eta<21
    


  6. La persona (o le persone) con il reddito massimo.

    Prima calcolo il reddito massimo, poi cerco le persone che lo prendono, così funziona anche se ci sono tante persone che prendono il reddito massimo

    SELECT * FROM persone WHERE reddito=(SELECT MAX(reddito) FROM persone)