[DMDB] SQL basics completed

This commit is contained in:
2026-06-23 15:51:58 +02:00
parent 03ed4ad541
commit 6641fb24bd
13 changed files with 262 additions and 38 deletions
@@ -7,16 +7,23 @@ To rename, we can set \texttt{I = Column as Name, Column2 as Name2}, etc
% TODO: Make RA an acronym, too
\inlinetheorem Every SPJR RA expression can be written in \texttt{SELECT ... FROM ... WHERE ...} form:
\begin{tables}{lll}{Operation & Notation & SQL}
Selection & $\sigma_c(R)$ & \texttt{SELECT * FROM R WHERE c;} \\
Projection & $\Pi_{A_1, \ldots, A_n} R$ & \texttt{SELECT A1, \ldots, An FROM R;} \\
Cartesian Product & $R_1 \times R_2$ & \texttt{SELECT * FROM (R1, R2);} \\
Rename & $\rho_{a, b, c} R$ & \texttt{SELECT A as a, \ldots, B as c FROM R;} \\
Union & $R_1 \cup R_2$ & \texttt{R1 UNION R2;} \\
Difference & $R_1 - R_2$ & \texttt{R1 EXCEPT R2;} \\
Intersection & $R_1 - R_2$ & \texttt{R1 INTERSECT R2;} \\
\begin{tables}{lll}{Operation & Notation & SQL}
Selection & $\sigma_c(R)$ & \texttt{SELECT * FROM R WHERE c;} \\
Projection & $\Pi_{A_1, \ldots, A_n} R$ & \texttt{SELECT A1, \ldots, An FROM R;} \\
Cartesian Product & $R_1 \times R_2$ & \texttt{SELECT * FROM (R1, R2);} \\
Rename & $\rho_{a, b, c} R$ & \texttt{SELECT A as a, \ldots, B as c FROM R;} \\
Union & $R_1 \cup R_2$ & \texttt{R1 UNION R2;} \\
Difference & $R_1 - R_2$ & \texttt{R1 EXCEPT R2;} \\
Intersection & $R_1 - R_2$ & \texttt{R1 INTERSECT R2;} \\
\end{tables}
Since \sql\ implements bag and not set semantics, there is a \texttt{DISTINCT} keyword, which is used to remove duplicates.
For the last three operations, \texttt{R1} and \texttt{R2} typically are other \sql\ statements:
Since \sql\ implements \gls{bag} and not set semantics, there is a \texttt{DISTINCT} keyword, which is used to remove duplicates.
It is to be applied in the \texttt{SELECT} clause (\texttt{I} above), e.g.
\mint{sql}|SELECT DISTINCT name FROM Data;|
For the last three operations, \texttt{R1} and \texttt{R2} typically are other \sql\ statements, example:
\mint{sql}|(SELECT name FROM FirstTable) UNION (SELECT name FROM SecondTable)|
In addition, to apply \textit{bag semantics}, as opposed to \textit{set semantics} append \texttt{ALL} to the expression (e.g. \texttt{UNION ALL})
We can also name the tables, e.g. $\texttt{T} = \texttt{One o, Two t}$, and then access columns from a specific table using
$\texttt{I} = \texttt{o.Col, b.Col}$, or the like.
@@ -0,0 +1,33 @@
\newpage
\subsubsection{Basic operators}
\label{sec:sql-basic-ops}
\paragraph{Logical Operators}
The following \sql\ logical operators are available (may not be exhaustive for all systems, \texttt{cop} is a comparison operator):
\begin{tables}{p{4.5cm}p{12cm}}{Operator & Description}
\texttt{P1 AND P2} & TRUE if \texttt{P1} and \texttt{P2} both are true \\
\texttt{P1 OR P2} & TRUE if one of \texttt{P1} or \texttt{P2}, or both are true \\
\texttt{C cop ALL query} & TRUE if all values \texttt{x} returned in \gls{subquery}\ \texttt{query} fulfil \texttt{C cop x} \\
\texttt{C cop ANY query} & TRUE if one (or more) values \texttt{x} returned in \gls{subquery}\ \texttt{query} fulfil \texttt{C cop x}.
\texttt{SOME} is logically equivalent \\
\texttt{C BETWEEN low AND high} & TRUE if numerical, text or date value of \texttt{C} is between \texttt{low} and \texttt{high}. Both ends inclusive, negatable \\
\texttt{C IN list} & TRUE if value of \texttt{C} is in the provided \texttt{list}.
List format: \texttt{(val, val2)}. List can also be a \gls{subquery}, negatable \\
\texttt{C LIKE R} & TRUE if value of \texttt{C} matches regex-like pattern \texttt{R}.
(\% matches any number of chars, \_ matches a single, arbitray character) \\
\texttt{EXISTS query} & TRUE if \gls{subquery}\ \texttt{query} retuns at least one row \\
% \texttt{IN} & TRUE if \\
\end{tables}
\paragraph{Comparison \& Arithmetic Operators}
\shade{gray}{Comparison Operators} $<, <=, =, >=, >$ are defined as usually, $<>$ is defined as not equal.
\shade{gray}{Arithmetic Operators} $+, -, *, /, \%$ are defined as usual.
We can use the arithmetic operators like this:
\mint{sql}|SELECT Value * 1.1 FROM Data;|
or in \texttt{WHERE} clauses like this:
\mint{sql}|SELECT Value FROM (Data a, Data b) WHERE a.Value = b.Value - 1;|
\inlineremark You may have noticed that in the above query, the same table was used twice.
This is referred to as a \bi{Self-Join} and can come in handy when comparing values in a single table.
@@ -0,0 +1,39 @@
\newpage
\subsubsection{Join}
Specifying two (or more) tables in the \texttt{FROM} clause will perform a cartesian product, e.g.
\mint{sql}|SELECT * FROM (Table1, Table2);|
returns all rows of the tables, next to each other.
Here, naming the tables in the \texttt{FROM} clause may come in handy, to not write out the entire name of the tables:
\mint{sql}|SELECT * FROM (Table1 t, Table2 s) WHERE t.id = s.id;|
\mint{sql}|SELECT * FROM (Table1, Table2) WHERE Table1.id = Table2.id;|
Both of the above statements produce the same result.
\paragraph{Nested Queries}
\label{sec:nested-queries}
To not have the cartesian product executed in the \texttt{FROM} clause, or to get a much more complex starting table, we can use a \gls{subquery}.
These are parenthesized normal SQL queries.
We can create an alias for them using an \texttt{AS name} clause after the parenthesis as follows
\mint{sql}|SELECT r.name FROM (SELECT * FROM Table) AS r;|
or alternatively, using a \texttt{WITH} clause (replace the dummy queries with real queries):
\mint{sql}|WITH CteName (SELECT * FROM Table) SELECT name FROM CteName;|
\paragraph{Join Operations}
If we don't specify the kind of join, an \texttt{INNER JOIN} is executed. The following three queries are equivalent
\mint{sql}|SELECT * FROM Student, Tests WHERE Student.PersNr = Tests.PersNr;|
\mint{sql}|SELECT * FROM Student JOIN Tests ON Student.PersNr = Tests.PersNr;|
\mint{sql}|SELECT * FROM Student JOIN Tests USING (PersNr);|
For the latter of the three, the parenthesis around the column are important, as omitting them is invalid syntax.
Other types of \texttt{JOIN} are:
\begin{itemize}
\item \texttt{NATURAL JOIN} (no \texttt{ON} required), joins on columns with same name
\item \texttt{LEFT/RIGHT/FULL OUTER JOIN} (requires \texttt{ON}), also returns non-matching rows from left, right or both sides, respectively
\end{itemize}
\begin{center}
\includegraphics[width=0.5\textwidth]{assets/join-types.png}
\end{center}
@@ -0,0 +1,41 @@
\newpage
\subsubsection{Aggregations, Grouping, Sorting}
\paragraph{Aggregations}
\sql\ supports (at least) the aggregation functions \texttt{SUM}, \texttt{MIN}, \texttt{MAX}, \texttt{AVG}, \texttt{COUNT},
whose output should be evident.
Please note that you cannot use the aggregation functions and still output another column,
as they produce a single value.
For each of the functions, you can optionally specify \texttt{DISTINCT}.
We typically want to specify an \texttt{AS} clause, to make the output nicer to read
\paragraph{Grouping}
Grouping is used to, well, group together the outputs on a column.
Using SQL, this is achieved using the \texttt{GROUP BY} clause.
We specify the columns on which the grouping should occur.
\hl{\textbf{\textit{IMPORTANT}}} We can only use aggregates and columns appearing in the \texttt{GROUP BY} clause in the \texttt{SELECT} clause.
Using a \texttt{JOIN} function, it is of course then possible to go back retrieve the other columns.
To apply filtering on the columns, the \texttt{HAVING} clause can be used.
It applies a comparison to a grouping column or an aggregate as specified in the \texttt{SELECT} clause:
\mint{sql}|SELECT COUNT(name) as cnt FROM Students GROUP BY Department HAVING cnt > 1;|
\paragraph{Sorting}
We can sort the output of any query using the \texttt{ORDER BY column DIRECTION} clause, where \texttt{DIRECTION} is to be replaced with \texttt{ASC} or \texttt{DESC}:
\mint{sql}|SELECT name FROM Students ORDER BY name DESC;|
\paragraph{Limit}
We can limit the number of columns to return using the \texttt{LIMIT} clause. Example:
\mint{sql}|SELECT * FROM Exams LIMIT 10;|
\paragraph{Example}
Below some examples of \sql\ Queries using grouping, aggregations, sorting and grouping
\inputcodewithfilename{sql}{}{code/sql/aggregations.sql}
@@ -0,0 +1,21 @@
\newpage
\subsubsection{Null}
\label{sec:sql-null}
Whenever we have incomplete information, we can set a column to be \texttt{NULL}.
If you have a column that has \texttt{NULL} values, when using \texttt{WHERE} clauses, these values are skipped.
\textit{However} if you are not filtering on the column, a \texttt{NULL} value is returned.
To check if a column is \texttt{NULL}, you can use the \texttt{IS} keyword:
\mint{sql}|SELECT * FROM Data WHERE name IS NULL|
\begin{itemize}[itemsep=-3pt]
\item In \texttt{GROUP BY}, all \texttt{NULL}s form a single group.
\item \texttt{COUNT(*)}, also counts rows with \texttt{NULL}
\item \texttt{COUNT(TheColWithNull)} ignores rows with \texttt{NULL}
\item Most other aggregations ignore \texttt{NULL}
\item If all rows in an aggregations are \texttt{NULL}, so is the result
\end{itemize}
The \texttt{OUTER JOIN} operators may (and likely will) introduce \texttt{NULL}
% TODO: Schema concepts? (slides 05, P20ff)
@@ -0,0 +1,23 @@
\subsubsection{Views}
Views are a useful way of abstracting a complex query and is the result of a stored query.
We can create views using the following template:
\mint{sql}|CREATE VIEW name AS query;|
We can then operate on it as if it were a table.
Common applications for views are privacy / access control, because you can limit access to tables only via certain views for every user;
Usability is also often much better due to having less complex queries to write - you are just writing them once.
\shade{orange}{How a view is evaluated}
This is quite simple in essence, the \texttt{VIEW}'s query is inserted into the query using the view.
It then is then optimized as it normally would be, too. Of course, it is likely that more optimization can and has to be done on views.
\paragraph{Updatable Views}
Updating Views refers to updating values of the tables in the views.
This is not straight forward and thus, many restrictions are placed on what kind of views are considered updatable.
In \sql, a view is updatable if and only if it involves \bi{one} base relation and its key, it does \bi{not} involve aggregates, groups or duplicate elimination.
In short, if there is one-to-one mapping between the view and base relation, it is updatable.