% !TEX root = ../main.tex

\begin{enumerate}[label=\alph*.]
    \item Uso di proiezione, join e restrizione.

    Mostrare l'IdRicetta e il Nome delle ricette create da birrai di nome
    Giovanni.
\begin{lstlisting}[style=SQLu,escapechar=@]
SELECT r.IdRicetta, r.Nome
FROM Ricette r
JOIN Persone p ON p.IdPersona = r.IdCreatrice
WHERE p.Nome = 'Giovanni'
\end{lstlisting}
    \item Uso di group by con having, where e sort.

    Per ogni birrificio che abbia fatto almeno un acquisto quest'anno,
    riportare l'IdBirrificio e il numero di diversi fornitori da cui ha
    acquistato quest'anno, se questo numero è almeno di 3.
    Ordinare il risultato dal birrificio che ha avuto più fornitori a quello
    che ne ha avuti meno.
\begin{lstlisting}[style=SQLu,escapechar=@]
SELECT fa.IdBirrificio,
       COUNT(DISTINCT fa.IdFornitore) DiversiFornitori
FROM Fatture fa
WHERE fa.Data >= '2020-01-01'
GROUP BY fa.IdBirrificio
HAVING COUNT(DISTINCT fa.IdFornitore) >= 3
ORDER BY COUNT(DISTINCT fa.IdFornitore) DESC
\end{lstlisting}
    \item Uso di join, group by con having e where.

    Dei fornitori da cui ha ordinato il birrificio `Pirati Rossi', mostrare la
    ragione sociale, l'importo totale e l'importo medio delle fatture, purché
    l'importo totale sia superiore a 10 euro.
\begin{lstlisting}[style=SQLu,escapechar=@]
SELECT fo.RagioneSociale, SUM(fa.Importo) ImportoTotale,
       AVG(fa.Importo) ImportoMedio
FROM Fornitori fo
JOIN Fatture fa ON fa.IdFornitore = fo.IdFornitore
JOIN Birrifici b ON b.IdBirrificio = fa.IdBirrificio
WHERE b.Nome = 'Pirati Rossi'
GROUP BY fo.IdFornitore, fo.RagioneSociale
HAVING SUM(fa.Importo) > 10
\end{lstlisting}
    \item Uso di select annidata con quantificazione esistenziale.

    Mostrare il soprannome de* birrai* che siano aut*r* di almeno una ricetta.
\begin{lstlisting}[style=SQLu,escapechar=@]
SELECT b.Soprannome
FROM Birraie b
WHERE EXISTS (SELECT *
              FROM Ricette r
              WHERE r.IdCreatrice = b.IdPersona)
\end{lstlisting}
\clearpage

    \item Uso di select annidata con quantificazione universale.

    Mostrare il nome e il cognome de* clienti che hanno ordinato da un solo
    birrificio.

\textbf{Traduco in notazione insiemistica:}
\begin{lstlisting}[style=SQLu,escapechar=@]
{p1.Nome, p1.Cognome | (p1 @$\in$@ Persone, pre1 @$\in$@ Prenotazioni,
                        pre1.IdCliente = p1.IdPersona,
                        pro1 @$\in$@ Produzioni,
                        pro1.IdProduzione = pre1.IdProduzione,
                        r1 @$\in$@ Ricette,
                        r1.IdRicetta = pro1.IdRicetta) .
    @$\forall$@ (pre2 @$\in$@ Prenotazioni, pre2.IdCliente = pre1.IdCliente
       pro2 @$\in$@ Produzioni, pro2.IdProduzione = pre2.IdProduzione,
       r2 @$\in$@ Ricette, r2.IdRicetta = pro2.IdRicetta) .
       (r2.IdBirrificio = r1.IdBirrificio)}
\end{lstlisting}

\textbf{Sostituisco il $\forall x . P$ con $\neg\exists x . \neg P$}
\begin{lstlisting}[style=SQLu,escapechar=@]
{p1.Nome, p1.Cognome | (p1 @$\in$@ Persone, pre1 @$\in$@ Prenotazioni,
                        pre1.IdCliente = p1.IdPersona,
                        pro1 @$\in$@ Produzioni,
                        pro1.IdProduzione = pre1.IdProduzione,
                        r1 @$\in$@ Ricette,
                        r1.IdRicetta = pro1.IdRicetta) .
    @$\neg\exists$@ (pre2 @$\in$@ Prenotazioni, pre2.IdCliente = pre1.IdCliente
        pro2 @$\in$@ Produzioni, pro2.IdProduzione = pre2.IdProduzione,
        r2 @$\in$@ Ricette, r2.IdRicetta = pro2.IdRicetta) .
        (r2.IdBirrificio @$\neq$@ r1.IdBirrificio)}
\end{lstlisting}

    \textbf{Scrivo quindi la query:}
\begin{lstlisting}[style=SQLu,escapechar=@]
SELECT p1.Nome, p1.Cognome
FROM Persone p1
JOIN Prenotazioni pre1 ON pre1.IdCliente = p1.IdPersona
JOIN Produzioni pro1 ON pro1.IdProduzione = pre1.IdProduzione
JOIN Ricette r1 ON r1.IdRicetta = pro1.IdRicetta
WHERE NOT EXISTS (SELECT *
                  FROM Prenotazioni pre2
                  JOIN Produzioni pro2
                       ON pro2.IdProduzione = pre2.IdProduzione
                  JOIN Ricette r2 ON r2.IdRicetta = pro2.IdRicetta
                  WHERE pre2.IdCliente = pre1.IdCliente
                        AND r2.IdBirrificio <> r1.IdBirrificio)
\end{lstlisting}

    \item Uso di subquery di confronto quantificato.

    Per ogni birrificio, mostrare l'IdBirrificio e l'ultimo NumeroLotto
    prodotto in quel birrificio (sapendo che il NumeroLotto è progressivo e che
    ogni ricetta è produtta in un solo birrificio).
\begin{lstlisting}[style=SQLu,escapechar=@]
SELECT r.IdBirrificio, pro1.NumeroLotto
FROM Produzioni pro1
JOIN Ricette r ON r.IdRicetta = pro1.IdRicetta
WHERE pro.NumeroLotto >= ANY (SELECT pro2.NumeroLotto
                              FROM Produzioni Pro2
                              WHERE pro2.IdRicetta = pro1.IdRicetta)
\end{lstlisting}
\end{enumerate}
\clearpage