\section{Normalformen}
    \subsection{1. Normalform}
        Jedes Attribut der Relation muss einen atomaren Wertebereich haben, und die Relation muss frei von Wiederholungsgruppen sein. \\
        \texttt{Atomar} bedeutet, dass ein Attribut nur eine Information enthalten darf, also dürfen bspw. Straße und Hausnummer nicht in einem Attribut gespeichert werden,
        sondern müssen aufgeteilt werdenn.\\
        Mit \texttt{Wiederholdungsgruppen} sind zum einen wiederholende Werte in einer Spalte gemeint (also bspw. in der Spalte Ort mehrmals der Wert Kirchheim) und zum anderen
        sich wiederholende Spalten (bspw. Spalten Standort1, Standort2, Standort3). \\

        Durch diese Normalform werden Abfragen der Datenbank überhaupt erst möglich gemacht. Ohne atomare Daten könnte nicht jeder Aspekt der Daten einzeln abgefragt werden.

    \subsection{2. Normalform}
        1. Normalform muss erfüllt sein. Ein Nichtprimärattribut darf nicht funktional von einer Teilmenge eines Schlüsselkandidaten abhängen. \\
        Das bedeutet: Attribute die nur von einem Teil eines Schlüssels und nicht von allen Schlüsseln in einer Tabelle (bei zusammengesetzten Schlüsseln)
        abhängig sind müssen ausgelagert werden, damit sie voll abhängig von ihrem Schlüssel werden. \\

        Durch diese Normalform modelliert jede Relation nur einen Sachverhalt.

    \subsection{3. Normalform}
        2. Normalform muss erfüllt sein. Kein Nichtschlüsselattribut darf transitiv von einem Schlüsselkandidaten abhängig sein. \\
        Das bedeutet: Wenn aus einem Attribut ein anderes Attribut ersichtlich wird, welches aber nicht durch den Schlüssel ersichtlich wird,
        ist es transitiv von dem ersten Attribut anhängig. \\
        Bsp.:
        %
        \begin{tabular}{| l | l | l | l |}
                CD\_ID & Albumtitel & Interpret & Gründungsjahr \\
                \hline
                1 & Not That Kind & Anastacia & 1999 \\
                2 & Wish you were here & Pink Floyd & 1965 \\
                3 & Freak of Nature & Anastacia & 1999 \\
        \end{tabular} \\
        %
        Das Gründungsjahr ist durch den Interpreten ersichtlich und nicht durch die CD\_ID. Das heißt, Interpret und Gründungsjahr sollten in eine Tabelle ausgelagert werden.

\section{SQL Befehle}
    \subsection{Tabelle erstellen}
       \begin{lstlisting}[frame=single]
        CREATE TABLE tabellenname 
        (id INT NOT NULL AUTO_INCREMENT,
        wert VARCHAR(255) NOT NULL, PRIMARY (id));
       \end{lstlisting}

    \subsection{Werte eintragen}
        \begin{lstlisting}[frame=single]
        INSERT INTO tabellenname (id, wert)
        VALUES (1, 'Test');
       \end{lstlisting}

    \subsection{Bestehende Werte ändern}
       \begin{lstlisting}[frame=single]
        UPDATE tabellenname 
        SET wert = 'Update TEST'
        WHERE id = 1;
       \end{lstlisting}

    \subsection{Werte aus Tabelle löschen}
       \begin{lstlisting}[frame=single]
        DELETE FROM tabellenname 
        WHERE id = 1;
       \end{lstlisting}

    \subsection{Komplette Tabelle löschen}
       \begin{lstlisting}[frame=single]
        DROP tabellenname;
       \end{lstlisting}

    \subsection{Alle Werte aus Tabelle löschen}
       \begin{lstlisting}[frame=single]
        TRUNCATE tabellenname;
       \end{lstlisting}

    \subsection{Werte anzeigen}
       \subsubsection{Alle anzeigen}
       \begin{lstlisting}[frame=single]
        SELECT * FROM tabellenname;
       \end{lstlisting}

    \subsubsection{Nur bestimmte Spalten anzeigen}
       \begin{lstlisting}[frame=single]
        SELECT werte FROM tabellenname;
       \end{lstlisting}

    \subsubsection{Spalten Beschriftungen}
       \begin{lstlisting}[frame=single]
        SELECT werte AS "Text" 
        FROM tabellenname;
       \end{lstlisting}

    \subsubsection{Zeilen zählen}
       Bei 3 Einträgen in Werte:
       \begin{lstlisting}[frame=single]
        SELECT COUNT(werte) AS "Anzahl Texte" 
        FROM tabellenname;
       \end{lstlisting}
        Ergebnis: Anzahl Texte 3

    \subsubsection{Werte aufsummieren}
       Angenommen die Tabelle enthält in der Spalte anzahl
       die Werte: 1, 3, 3, 7
       \begin{lstlisting}[frame=single]
        SELECT SUM(anzahl) AS "Summe Anzahl" 
        FROM tabellenname;
       \end{lstlisting}
       Ergebnis wäre dann: Summe Anzahl 14

    \subsubsection{Weitere Rechenfunktionen}
        Außer COUNT() und SUM() gibt es noch:
        \begin{itemize}
            \item AVG: Average, Durchschnitt über Werte bilden
            \item MIN: Den kleinsten Wert ausgeben
            \item MAX: Den größten Wert ausgeben
            \item ROUND(spalte, dezimalstellen): Gerundete Werte ausgeben
        \end{itemize}


    \subsubsection{Werte miteinander verrechnen}
       Angenommen die Tabelle enthält in der Spalte anzahl
       die Werte: 4, 2 und in der Spalte preis die Werte
       5, 4.
       \begin{lstlisting}[frame=single]
        SELECT (anzahl * preis) AS "Preis gesamt" 
        FROM tabellenname;
       \end{lstlisting}
       Die Ergebnisse wären dann: 20, 8



    \subsection{Werte sortieren}
       Eine unsortierte Liste bspw.: 7, 3, 1, 3
       \begin{lstlisting}[frame=single]
        SELECT werteunsortiert
        FROM tabellenname
        ORDER BY werteunsortiert ASC;
       \end{lstlisting}
       Aufsteigend sortiert wird mit \texttt{ASC}. \\ 
       Absteigend sortiert wird mit \texttt{DESC}. \\ 
       Ergibt nach dem sortieren mit ASC: 1, 3, 3, 7 \\ 
       Nach dem sortieren mit DESC: 7, 3, 3, 1 \\
        
        \subsubsection{Werte zufällig anordnen}
            Manchmal kann es sinnvoll sein,
            Werte in eine zuällige Reihenfolge zu bringen.
        \begin{lstlisting}[frame=single]
        SELECT werteunsortiert
        FROM tabellenname
        ORDER BY RAND();
       \end{lstlisting}

    \subsection{Werte gruppieren}
       Angenommen es gibt die Kategorien: 1, 3, 3, 7.
       Es sollen die einzelnen Kategorien und ihre Häufigkeit angezeigt werden (optional).
       \begin{lstlisting}[frame=single]
        SELECT werte, COUNT(werte) 
        FROM tabellenname
        GROUP BY werte;
       \end{lstlisting}
        Die Ergebnisse: 1 $\Rightarrow$ 1x, 3 $\Rightarrow$ 2x, 7 $\Rightarrow$ 1x 

    \subsubsection{HAVING bei GROUP BY}
        Mit WHERE kann man vor einer Gruppierung filtern.
        Soll aber nach einem GROUP BY gefiltert werden 
        (damit die Gruppierung nicht verfälscht wird)
        geht das nicht mit WHERE sondern nur mit HAVING.
        Die Syntax für das filtern bleibt dabei die gleiche wie bei WHERE.
       \begin{lstlisting}[frame=single]
        SELECT werte, COUNT(werte) 
        FROM tabellenname
        GROUP BY werte
        HAVING werte > 1;
       \end{lstlisting}
 
    \subsection{Die ersten X Zeilen ausgeben}
        Wenn bspw. bei einer Highscore Liste nur die ersten
        5 Kandidaten relevant sind, können diese mit LIMIT beschränkt werden.
       \begin{lstlisting}[frame=single]
        SELECT werte
        FROM tabellenname
        ORDER BY werteunsortiert DESC
        LIMIT 5;
       \end{lstlisting}
        Hiermit werden die 5 größsten Werte ausgegeben. 

    \subsection{Tabellen miteinander verknüpfen - JOINS}
        \subsubsection{INNER JOIN}
            Tabelle Person (id, name, fk\_ort) \\
            Tabelle Ort (id, name, plz) \\

            \begin{lstlisting}[frame=single]
             SELECT Person.name, Ort.plz
             FROM Person INNER JOIN Ort
             ON Person.fk_ort = Ort.id;
            \end{lstlisting}
            Jetzt werden alle Personen ausgegeben,
            die einen Ort zugewiesen haben. Personen die keinen Ort
            zugewiesen werden, fallen weg.
        \subsubsection{LEFT JOIN}
            Funktioniert genau gleich wie INNER JOIN, jedoch wird die linke
            Schnittmenge verwendet. Das bedeutet bei FROM Person LEFT JOIN Ort
            ist Person die linke Tabelle. Das heißt es werden alle Personen angezeigt,
            auch wenn diese keinen Ort eingetragen haben.
        \subsubsection{RIGHT JOIN}
            Genau das selbe Prinzip wie LEFT JOIN, bloß diesesmal wird die rechte
            Schnittmenge verwendet. Es würden in diesem Beispiel also alle Orte angezeigt
            werden, auch wenn dazu keine Personen zugeordnet sind (in diesem Beispiel eher
            weniger sinnvoll). Jedes RIGHT JOIN kann in ein LEFT JOIN umgeschrieben und umgekehrt.
            Es ist nur eine Darstellungssache, wenn man bspw. aus einem ERM Modell die Darstellung
            beibehalten möchte.
