% !TEX root = ../main.tex
\subsection{Query a}

\paragraph{Piano di accesso logico della query a}
\begin{center}
  \begin{forest}, baseline, qtree
      [{$\pi^{b}$ r.IdRicetta , r.Nome}
          [{$\bowtie$ p.IdPersona = r.IdCreatrice}
              [{$\sigma$ p.Nome = 'Giovanni'}
                  [Persone p]
              ]
              [Ricette r]
          ]
      ]
  \end{forest}
\end{center}

Non c'è in questo caso differenza tra $\pi^{b}$ e $\pi$: non ci possono essere
duplicati.
\paragraph{Piano di accesso fisico della query a senza indici}
\begin{center}
  \begin{forest}, baseline, qtree
      [{Project(\{r.IdRicetta , r.Nome\})}
          [{SortMerge(p.IdPersona = r.IdCreatrice)}
              [{Sort([p.IdPersona])}
                  [{Project(\{p.IdPersona\})}
                    [{Filter(p.Nome = 'Giovanni')}
                      [{TableScan(Persone p)}]
                    ]
                  ]
              ]
              [{Sort([r.IdCreatrice])}
                [{Project(\{r.IdRicetta, r.Nome, r.IdCreatrice\})}
                  [{TableScan(Ricette r)}]
                ]
              ]
          ]
      ]
  \end{forest}
\end{center}

\paragraph{Piano di accesso fisico della query a con due indici}
\begin{center}
  \begin{forest}, baseline, qtree
      [{Project(\{r.IdRicetta , r.Nome\})}
          [{IndexNestedLoop(p.IdPersona = r.IdCreatrice)}
              [{IndexFilter(Persone p,\\ IndPN, p.Nome = 'Giovanni')}]
              [{IndexFilter(Ricette r,\\IndRC, r.IdCreatrice = p.IdPersona)}]
          ]
      ]
  \end{forest}
\end{center}
Indici necessari: \texttt{IndPN} (indice della tabella Persone sull’attributo
Nome) e \texttt{IndRC} (indice della tabella Ricette sull'attributo Creatrice).

\clearpage
\subsection{Query b}

\paragraph{Piano di accesso logico della query b}
\begin{center}
  \begin{forest}, baseline, qtree
    [{$\tau$[-DiversiFornitori]}
      [{$\pi^{b}$ fa.IdBirrificio, COUNT(DISTINCT fa.IdFornitore) DiversiFornitori}
        [{$\sigma$ COUNT(DISTINCT fa.IdFornitore) $>=$ 3}
            [\{fa.IdBirrificio\} {$\gamma$ \{COUNT(DISTINCT fa.IdFornitore)\}}
                [{$\sigma$ fa.Data $>=$ '2020-01-01'}
                  [Fatture fa]
                ]
            ]
        ]
      ]
    ]
  \end{forest}
\end{center}

Non c'è in questo caso differenza tra $\pi^{b}$ e $\pi$: non ci possono essere
duplicati, in quanto la GROUP BY raggruppa per IdBirrificio.
\paragraph{Piano di accesso fisico della query b senza indici}
\begin{center}
  \begin{forest}, baseline, qtree
    [{Sort[-DiversiFornitori]}
        [{Project(\{fa.IdBirrificio, COUNT(DISTINCT fa.IdFornitore) DiversiFornitori\})}
            [{Filter(COUNT(DISTINCT fa.IdFornitore) $>=$ 3)}
                [{GroupBy(\{fa.IdBirrificio\}, \{COUNT(DISTINCT fa.IdFornitore)\})}
                    [{Sort([fa.IdBirrificio])}
                        [{Filter(fa.Data $>=$ '2020-01-01')}
                            [{TableScan(Fatture fa)}]
                        ]
                    ]
                ]
            ]
        ]
    ]
  \end{forest}
\end{center}
Il sort sull'attributo dimensione di analisi prima della GroupBy è necessario,
in quanto non è garantito che i record della tabella Fatture siano raggruppati
per IdBirrificio.
Lo sarebbero se l'organizzazione primaria della tabella fosse sequenziale
proprio su questo attributo, il che è estremamente poco probabile.
\clearpage
\paragraph{Piano di accesso fisico della query b con un indice}
\begin{center}
  \begin{forest}, baseline, qtree
      [{Sort[-DiversiFornitori]}
        [{Project(\{fa.IdBirrificio, COUNT(DISTINCT fa.IdFornitore) DiversiFornitori\})}
            [{Filter(COUNT(DISTINCT fa.IdFornitore) $>=$ 3)}
                [{GroupBy(\{fa.IdBirrificio\}, \{COUNT(DISTINCT fa.IdFornitore)\})}
                    [{Sort([fa.IdBirrificio])}
                        [{IndexFilter(Fatture fa, IndFD, fa.Data $>=$ '2020-01-01')}]
                    ]
                ]
            ]
        ]
    ]
  \end{forest}
\end{center}
Indice necessario: \texttt{IndFD} (indice della tabella Fatture sull’attributo
Data).
Il sort sull'attributo IdBirrificio prima della GroupBy è necessario, in quanto
i record in input sono ordinati per data, il che non ci garantisce che siano
raggruppati per IdBirrificio (che è dimensione di analisi).

\subsection{Query c}

\paragraph{Piano di accesso logico della query c}
\begin{center}
  \begin{forest}, baseline, qtree
      [{$\pi^{b}$ fo.RagioneSociale, SUM(fa.Importo) ImportoTotale, AVG(fa.Importo) ImportoMedio}
          [$\sigma$ SUM(fa.Importo) $>$ 10
              [{\{fo.IdFornitore, fo.RagioneSociale\} $\gamma$ \{SUM(fa.Importo), AVG(fa.Importo)\}}
                  [{$\bowtie$ fa.IdFornitore = fo.IdFornitore}
                      [{Fornitori fo}]
                      [{$\bowtie$ fa.IdBirrificio = b.IdBirrificio}
                          [{$\sigma$ b.Nome = 'Pirati Rossi'}
                              [{Birrifici b}]
                          ]
                          [{Fatture fa}]
                      ]
                  ]
              ]
          ]
      ]
  \end{forest}
\end{center}

In questo caso non ci dovrebbe essere differenza tra $\pi^{b}$ e $\pi$: non ci
devono essere due fornitori con la stessa ragione sociale (la ragione sociale
è chiave naturale); è comunque possibile un errore di inserimento se non ho
impostato un vincolo di unicità anche su questo attributo, che non ho scelto
come chiave primaria della tabella.
\clearpage

\paragraph{Piano di accesso fisico della query c senza indici}
\begin{center}
  \begin{forest}, baseline, qtree
      [{Project(\{fo.RagioneSociale,\\SUM(fa.Importo) ImportoTotale, AVG(fa.Importo) ImportoMedio\})}
          [{Filter(SUM(fa.Importo) $>$ 10)}
              [{GroupBy(\{fo.IdFornitore,fo.RagioneSociale\}, \{SUM(fa.Importo), AVG(fa.Importo)\})}
                  [{MergeSort(fa.IdFornitore = fo.IdFornitore)}
                      [{Sort([fo.IdFornitore])}
                          [{Project(\{fo.IdFornitore,\\fo.RagioneSociale\})}
                              [{Fornitori fo}]
                          ]
                      ]
                      [{Sort([fa.IdFornitore])}
                          [{Project(\{fa.IdFornitore, fa.Importo\})}
                              [{MergeSort(fa.IdBirrificio = b.IdBirrificio)}
                                  [{Sort([b.IdBirrificio])}
                                      [{Project(\{b.IdBirrificio\})}
                                          [{Filter(b.Nome = 'Pirati Rossi')}
                                              [{TableScan(Birrifici b)}]
                                          ]
                                      ]
                                  ]
                                  [{Sort([fa.IdBirrificio])}
                                      [{Project(\{fa.IdBirrificio,\\fa.IdFornitore fa.Importo\})}
                                          [{Fatture fa}]
                                      ]
                                  ]
                              ]
                          ]
                      ]
                  ]
              ]
          ]
      ]
  \end{forest}
\end{center}

\clearpage
\paragraph{Piano di accesso fisico della query c con due indici}
\begin{center}
  \begin{forest}, baseline, qtree
      [{Project(\{fo.RagioneSociale,\\SUM(fa.Importo) ImportoTotale, AVG(fa.Importo) ImportoMedio\})}
          [{Filter(SUM(fa.Importo) $>$ 10)}
              [{GroupBy(\{fo.IdFornitore,fo.RagioneSociale\}, \{SUM(fa.Importo), AVG(fa.Importo)\})}
                  [{MergeSort(fa.IdFornitore = fo.IdFornitore)}
                      [{Sort([fo.IdFornitore])}
                          [{Project(\{fo.IdFornitore,\\fo.RagioneSociale\})}
                              [{Fornitori fo}]
                          ]
                      ]
                      [{Sort([fa.IdFornitore])}
                          [{Project(\{fa.IdFornitore, fa.Importo\})}
                              [{IndexNestedLoop(fa.IdBirrificio = b.IdBirrificio)}
                                  [{IndexFilter(Birrifici b, IndBN,\\b.Nome = 'Pirati Rossi')}]
                                  [{IndexFilter(Fatture fa, IndFIdB,\\fa.IdBirrificio = b.IdBirrificio)}]
                              ]
                          ]
                      ]
                  ]
              ]
          ]
      ]
  \end{forest}
\end{center}
Indici necessari: \texttt{IndBN} (indice della tabella Birrifici sull’attributo
Nome) e \texttt{IndFIdB} (indice della tabella Fatture sull'attributo
IdBirrificio).