And again, we have the option to do this via sorting or hashing: \begin{itemize} \item \bi{Sorting}: Sort on the attribute. Then scan the sorted tuples, computing running aggregate (such as max/min, average, etc). When a new group is encountered, then we output the aggregate. The cost is \cost{$\texttt{cost}_\texttt{sort}(R) + \texttt{cnt}(R)$}. Alternatively, we can already compute the aggregates on the last step of sorting (the merge) to save some time. The limiting factor then becomes the sorting and the cost is \cost{$\texttt{cost}_\texttt{sort}(R)$} \item \bi{Hashing}: We hash the attribute and now each hash table entry is a group of all records with this value of the attribute. For each one of these groups, we compute the aggregate. The cost is \cost{$\texttt{cnt}(R)$} If the table is too large for memory, we use a two-step approach, as before. The cost is then very similar \cost{$\texttt{cnt}(R) + B$} for $B$ tables. \end{itemize}