# SQL ## Conditions Basics Manchmal möchten wir Datensätze abrufen, die eine bestimmte Bedingung erfüllen. Zum Beispiel - alle Datensätze abrufen, die den Familiennamen „Aothly“ haben - alle Datensätze abrufen, bei denen der Betrag größer als 5 ist - Alle Datensätze mit dem Land „Mexico“ abrufen Um Bedingungen hinzuzufügen, können wir das `WHERE`-Schlüsselwort verwenden Zum Beispiel hier ist eine **Verkäufe**-Tabelle: | Münze | Menge | | ----- | ----- | | AGK | 13 | | GOL | 21 | | KLA | 15 | | AGK | 18 | Um alle Datensätze mit der Coin „AGK“ abzurufen, schreibt man: ```sql SELECT * FROM sales WHERE coin = 'AGK' ``` Um alle Datensätze mit `amount` kleiner oder gleich 20 abzurufen, schreibt man: ```sql SELECT * FROM sales WHERE amount <= 20 ``` ### Unique values Angenommen man hat die folgende Tabelle: **Verkäufe** | | Land | Stadt | Betrag | | --- | ----------- | -------- | ------ | | 1 | Polen | Warschau | 13 | | 2 | Deutschland | Berlin | 24 | | 3 | Polen | Katowice | 56 | Man möchte alle Länder wissen, in denen das Produkt verkauft wurde. Wenn man die normale Abfrage, die man kennt, verwendet: `SELECT country from sales` liefert sie `Poland`, `Germany`, `Poland`. Das ist nicht das, wonach man sucht, weil Polen zweimal wiederholt wird. Um es zu lösen, kann man das `DISTINCT`-Schlüsselwort verwenden: ### NOT Das `NOT`-Schlüsselwort bedeutet, dass man nicht möchte, dass die Bedingung erfüllt wird. Zum Beispiel betrachte man die folgende **people**-Tabelle: | Name | Alter | Geschlecht | | ------ | ----- | ---------- | | Joas | 13 | männlich | | Holwa | 17 | männlich | | Nohlas | 24 | weiblich | | Polar | 23 | männlich | | Loopa | 18 | weiblich | ```sql SELECT * FROM people WHERE NOT gender = 'male' ``` Dies wird das Ergebnis sein: | Name | Alter | Geschlecht | | ------ | ----- | ---------- | | Nohlas | 24 | weiblich | | Loopa | 18 | weiblich | Das `NOT`-Schlüsselwort kehrt die Bedingung im Wesentlichen um. Zum Beispiel sind die folgenden Abfragen gleich: ```sql WHERE age > 20``` ```sql WHERE NOT age <= 20``` ### AND Das `AND`-Schlüsselwort bedeutet, dass **beide** Bedingungen wahr sein müssen; wenn eine von ihnen nicht der Fall ist, wird die Bedingung nicht erfüllt. Zum Beispiel ist hier eine `people`-Tabelle: | Name | Alter | Geschlecht | | ------ | ----- | ---------- | | Joas | 13 | männlich | | Holwa | 17 | männlich | | Nohlas | 24 | weiblich | | Polar | 23 | männlich | | Loopa | 18 | weiblich | Die folgende Abfrage: ```sql SELECT * FROM people WHERE gender = "female" AND age < 20 ``` bedeutet, dass man nach allen Datensätzen sucht, bei denen das Geschlecht „female“ ist und das Alter kleiner als 20 ist. Dies wird das Ergebnis sein: | Name | Alter | Geschlecht | | ----- | ----- | ---------- | | Loopa | 18 | weiblich | ### OR Das `OR`-Schlüsselwort bedeutet, dass eine der Bedingungen wahr sein soll. Zum Beispiel betrachtet man die folgende **people**-Tabelle: | name | age | gender | | ------ | --- | ------ | | Joas | 13 | male | | Holwa | 17 | male | | Nohlas | 24 | female | | Polar | 23 | male | | Loopa | 18 | female | ```sql SELECT * FROM people WHERE gender = 'female' OR age < 20 ``` Diese Abfrage bedeutet, dass man nach allen Datensätzen sucht, bei denen entweder das Geschlecht weiblich ist oder das Alter unter 20 liegt. Das wird das Ergebnis sein: | Name | Alter | Geschlecht | | ------ | ----- | ---------- | | Joas | 13 | männlich | | Holwa | 17 | männlich | | Nohlas | 24 | weiblich | | Loopa | 18 | weiblich | ## Kombination von Conditions Das Erstellen einer Abfrage mit nur einer Bedingung ist nicht ausreichend. Manchmal möchte man etwas Komplizierteres überprüfen. Dafür haben SQL (und viele andere Programmiersprachen) die AND-, OR- und NOT-Schlüsselwörter, um unsere Fähigkeit zu verbessern, das gewünschte Ergebnis abzurufen. Die AND und OR Schlüsselwörter werden wie folgt verwendet: ```sql SELECT col1, col2 FROM table1 WHERE condition1 AND condition2 OR condition3 ... ``` Man kann so viele Bedingungen wie man will zusammen stapeln. ## Sortierung (ORDER BY) `... ORDER BY ASC`, das wird standardmäßig gesetzt `ASC` --> Aufsteigend --> kleinster Wert zuerst `DESC` --> Absteigend --< Größter Wert zuerst ### Beispiele und Erklärung Beim Abfragen einer Datenbank kann die Organisation der Ergebnisse in einer sinnvollen Reihenfolge die Datenanalyse erheblich effizienter machen. Um das Ergebnis zu sortieren, verwendet man das ORDER BY-Schlüsselwort und danach sollte man angeben, nach welchem Feld man sortiert. Standardmäßig sortiert es in aufsteigender Reihenfolge. Zum Beispiel betrachten Sie die folgende **competition**-Tabelle: | runner_id | age | avg_speed | | --------- | --- | --------- | | 1 | 47 | 3.65 | | 2 | 62 | 3.07 | | 3 | 57 | 6.82 | | 4 | 56 | 4.34 | | 5 | 25 | 4.93 | | 6 | 40 | 3.94 | | 7 | 23 | 6.58 | | 8 | 40 | 3.43 | `SELECT * FROM competition WHERE age > 50 ORDER BY avg_speed` Dies ist das Ergebnis | runner_id | age | avg_speed | | --------- | --- | --------- | | 2 | 62 | 3.07 | | 4 | 56 | 4.34 | | 3 | 57 | 6.82 | Um anzugeben, wie diese Daten sortiert werden sollen, können wir die `DESC`- oder `ASC`-Schlüsselwörter nach dem Namen der Spalte hinzufügen. `ORDER BY avg_speed ASC` ## Datumsangaben behandeln Daten in SQL haben ein bestimmtes Format und wir können sie ähnlich wie Zahlen abfragen. Um ein Datum in einer Abfrage zu schreiben, verwendet man das Format: YYYY-MM-DD (2012-09-24) Um Datumsangaben abzufragen, kann man alle Operatoren verwenden, wie – größer (`>`), kleiner (`<`) oder gleich (`=`) innerhalb des Schlüsselworts WHERE: ```sql SELECT * FROM table1WHERE col1 > '2011-01-13' ``` Wir können sogar das Schlüsselwort BETWEEN verwenden: ```sql SELECT * FROM table1WHERE col1 BETWEEN '2010-01-01' AND '2010-02-25 ``` ############################################################# ## Eigenschaften einer Tabelle ```sql DESCRIBE ``` oder ```sql SHOW COLUMNS FROM ``` ## Neuer Datensatz ```sql INSERT INTO (,...) VALUES (,,...) ``` ## Update Datensatz ```sql UPDATE set = , = , ... WHERE ``` ## Anlegen eines Users mit Rechten ```sql CREATE USER 'sammy'@'localhost' IDENTIFIED BY 'password'; ``` ## Rechte setzen ```sql GRANT PRIVILEGE ON database.table TO 'username'@'host'; ``` - `CREATE`: Er­mög­licht es Benutzern, eine Datenbank oder Tabelle zu erstellen. - `SELECT`: Erlaubt Benutzern, Daten abzurufen. - `INSERT`: Er­mög­licht es Benutzern, neue Einträge in Tabellen hin­zu­zu­fü­gen. - `UPDATE`: Er­mög­licht es Benutzern, be­stehen­de Einträge in Tabellen zu ändern. - `DELETE`: Er­mög­licht es Benutzern, Ta­bel­len­ein­trä­ge zu löschen. - `DROP`: Benutzer können ganze Da­ten­bank­ta­bel­len löschen. Somit also ```sql GRANT SELECT, CREATE ON database.table TO 'username'@'host'; ``` ## Einlesen der Berechtigungstabellen Aktivieren mit ```sql FLUSH PRIVILEGES; ``` ## Entziehen von Rechten ```sql REVOKE type_of_permission ON database_name.table_name FROM 'username'@'host'; ``` ## Anzeigen der aktuellen Berechtigungen ```sql SHOW GRANTS FOR 'username'@'host'; ``` ## User löschen ```sql DROP USER 'username'@'localhost'; ``` ## IN IN ist die vereinfachte Schreibweise für OR. Hier wird jeder Begriff, die per Kommata getrennt sind, der in der Klammer nach dem IN steht per OR abgefragt ## BETWEEN Anstatt zu schreiben: ```sql WHERE col1 >= 5 AND col1 <= 10 ``` Kann man folgendes schreiben: ```sql WHERE col1 BETWEEN 5 AND 10 ``` Der `BETWEEN`-Operator ist inklusiv, was bedeutet, dass er die Grenzwerte (in diesem Fall 5 und 10) in die Ergebnisse einschließt. Dies macht die SQL-Abfragen sauberer und lesbarer, insbesondere bei der Arbeit mit Datumsbereichen oder numerischen Intervallen. ## LIKE Das `LIKE`-Schlüsselwort wird verwendet, um Ähnlichkeiten von Zeichenketten zu prüfen. Beispielsweise, wenn wir alle Datensätze abrufen möchten, deren Name mit dem Buchstaben `a` beginnt, dann verwenden wir das `LIKE`-Schlüsselwort. Zwei Hauptwildcards werden verwendet: - `%` - steht für eine beliebige Anzahl von Zeichen - `_` - steht für genau ein Zeichen Zum Beispiel: - `%a` - bedeutet jede Zeichenkette, die mit `a` endet - `a%` - bedeutet jede Zeichenkette, die mit `a` beginnt - `%a%` - bedeutet jeder String, der `a` enthält - `_a%` - bedeutet, dass der Buchstabe `a` der zweite Buchstabe im String ist - `%a__` - bedeutet, dass der String `a` an der drittletzten Stelle enthält Um es zu verwenden, schreiben wir: ```sql SELECT col1, col2, ... FROM table1 WHERE col1 LIKE '%a__' ``` **Beispiel** Suche aller Personen deren Name mit Gross-K beginnt und mit klein-a endet, sortiert nach Name in absteigender Reihenfolge ```sql select * from people where name like 'K%a' order by name desc; ``` ## Tabelle anlegen ```sql CREATE TABLE Persons ( PersonID int PRIMARY KEY AUTO_INCREMENT, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255) ); ``` | **Datentyp** | **MySQL-Format** | **PostgreSQL-Format** | **INSERT INTO Beispiel** | |:----------------------------------------------------- |:-------------------------------------------- |:-------------------------------------------- |:------------------------------------------------------------------------ | | **Zeichenkette (TEXT, VARCHAR, CHAR usw.)** | Eingeschlossen in einfache Anführungszeichen | Eingeschlossen in einfache Anführungszeichen | `INSERT INTO tableName (columnName) VALUES ('John Doe');` | | **Zahl (Ganzzahl, Dezimalzahl, Gleitkommazahl usw.)** | Keine Anführungszeichen | Keine Anführungszeichen | `INSERT INTO tableName (columnName) VALUES (25);` | | **Boolescher Wert** | WAHR oder FALSCH (oder 1 und 0) | WAHR oder FALSCH | `INSERT INTO tableName (columnName) VALUES (TRUE);` | | **Datum, Uhrzeit und Zeitstempel** | JJJJ-MM-TT HH:MM:SS | JJJJ-MM-TT HH:MM:SS | `INSERT INTO tableName (dateTimeColumn) VALUES ('2023-08-18 12:45:00');` | ## Bestimmte Zeilen aus einer Tabelle kopieren Wenn man bestimmte Zeilen basierend aus einer Bedingung kopieren möchten, kann man die `SELECT`Anweisung mit . kombinieren `INSERT INTO`. **Syntax** : ```sql INSERT INTO table_name1 SELECT columns FROM table_name2 WHERE condition; ``` ## Import einer Datenbank ```bash mysql < ``` ## Rechte für die Datenbank ```sql CREATE USER 'benutzer'@'localhost' IDENTIFIED BY 'passwort'; ``` ```sql GRANT ALL PRIVILEGES ON .* to 'benutzer'@'localhost'; ``` ```sql FLUSH PRIVILEGES; ``` ## Fetch / Offset Hiermit kann man sich eine Anzahl von Zeilen ausgeben lassen, welche zwischen Offset und Limit liegen, oder aber über den zweiten Weg mit Fetch ```sql SELECT first_name, last_name, FROM employees ORDER BY first_name, last_name OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY; ``` Hier werden die ersten fünf Zeilen übersprungen und die nächsten fünf ausgegeben. ### Abfrage einer bestimmten Anzahl von Zeilen Beispiel: von Zeile 10 (Offset) 10 Zeilen weiter (LIMIT) ```sql select * from .... limit 10 offset 10 ``` oder ```sql offset 228 --Skipping the first 228 rows in the result set --Fetching the next 10 rows only after the offset FETCH NEXT 10 ROWS ONLY; ``` ### The AS keyword Klare und beschreibende Spaltennamen sind essenziell, um Daten auf sinnvolle Weise darzustellen. Wenn Sie eine Tabelle mit schlechten Spaltennamen zeigen, wird es für Ihr Publikum schwer sein zu verstehen, wovon Sie sprechen. Um Spaltennamen zu ändern, können Sie das AS-Schlüsselwort verwenden. ```sql SELECT col1 AS firstColumn, col2 AS secondColumn, ... FROM table1 ``` ## The LIKE keyword Das LIKE-Schlüsselwort wird verwendet, um Ähnlichkeiten von Zeichenketten zu prüfen. Beispielsweise, wenn wir alle Datensätze abrufen möchten, deren Name mit dem Buchstaben a beginnt, dann verwenden wir das LIKE-Schlüsselwort. Zwei Hauptwildcards werden verwendet: `% `- steht für eine beliebige Anzahl von Zeichen `_ `- steht für genau ein Zeichen Zum Beispiel: `%a` - bedeutet jede Zeichenkette, die mit a endet `a%` - bedeutet jede Zeichenkette, die mit a beginnt `%a%` - bedeutet jeder String, der a enthält `_a%` - bedeutet, dass der Buchstabe a der zweite Buchstabe im String ist `%a__` - bedeutet, dass der String a an der drittletzten Stelle enthält Um es zu verwenden, schreiben wir: ```sql SELECT col1, col2, ... FROM table1 WHERE col1 LIKE '%a__' ``` ## Mathematical Columns ### Verfügbare Tabellen und Spalten: products: id, price, quantity Erstellen Sie eine Abfrage, die Folgendes berechnet: 1. Eine Spalte namens total_value, die den Preis mit der Menge multipliziert und eine feste Versandpauschale von 15 hinzufügt 2. Eine Spalte namens discounted_value, die: - Zuerst den Preis mit der Menge multipliziert - Dann einen 20%-Rabatt anwendet (multipliziert mit 0.8) - Schließlich eine feste Versandpauschale von 10 hinzufügt Versuchen Sie, Klammern angemessen zu verwenden, um sicherzustellen, dass die Berechnungen in der richtigen Reihenfolge durchgeführt werden! ```sql select (price * quantity + 15) as total_value, (price * quantity * 0.8 + 10) as discounted_value from products ``` ## The Modulo Operation Der Modulo-Operator `%` gibt den Rest an, der nach der Division einer Zahl durch eine andere übrig bleibt. dividend % divisor dividend: Die Zahl, die geteilt wird. divisor: Die Zahl, durch die der Dividend geteilt wird. Zum Beispiel ```sql 10 % 3 ``` Hier wird 10 durch 3 geteilt. Die 3 passt dreimal in die 10, mit einem Rest von 1. Daher wird result 1 sein. Normalerweise wird Modulo verwendet, um zu prüfen, ob eine Zahl gerade oder ungerade ist: - Wenn eine Zahl gerade ist, lässt die Division durch 2 einen Rest von 0. - Wenn eine Zahl ungerade ist, lässt die Division durch 2 einen Rest von 1. Finden Sie zum Beispiel Zeilen mit geraden Nummern: ```sql SELECT * FROM table WHERE id % 2 = 0; ``` Oder zum Durchlaufen von Werten: ```sql number % 12 (gibt 0-11 zurück) number % 8 (gibt 0-7 zurück) ``` Gruppieren Sie zum Beispiel Elemente in 5er-Gruppen: SELECT item_number % 5 as group_number FROM inventory; Welche Abfrage wählt nur ungerade Zeilen aus? SELECT * FROM users WHERE id % 2 = 1; Vervollständigen Sie die Abfrage, um Produkte in 4er-Gruppen zu gruppieren: SELECT product_id % 4 as group_num FROM products; -- hier wurde nur % hinzugefügt Welchen Wertebereich kann number % 7 zurückgeben? 0 through 6 Der Rest bei der Division durch 7 ist immer kleiner als 7 und reicht von 0 bis 6. ##################################################### Challenge zu modulo > Verfügbare Tabellen und Spalten: > > - `**products**`**:** `**id**`**,** `**price**`, `quantity` > - | products | | | | > | -------- | --- | ----- | -------- | > | | id | price | quantity | > | 1 | 1 | 154 | 18 | > | 2 | 2 | 98 | 3 | > | 3 | 3 | 54 | 15 | > | 4 | 4 | 142 | 14 | > | 5 | 5 | 70 | 2 | > | 6 | 6 | 189 | 7 | > | 7 | 7 | 44 | 3 | > | 8 | 8 | 62 | 16 | > | 9 | 9 | 101 | 8 | > | 10 | 10 | 192 | 9 | > | 11 | 11 | 4 | 21 | > | 12 | 12 | 208 | 3 | > | 13 | 13 | 144 | 5 | > | 14 | 14 | 68 | 98 | > | 15 | 15 | 5 | 14 | Erstellen Sie eine Abfrage, die: 1. Die Produkt-ID anzeigt 2. Jedes Produkt einem von drei Qualitätskontrollteams (0, 1 oder 2) **basierend auf der Produkt-ID unter Verwendung des Modulo-Operators** zuweist; nennen Sie diese Spalte `quality_control` 3. Nur Produkte einschließt, bei denen die **Spalte quantity eine ungerade Zahl enthält** (z. B. 1, 3, 5, 7...) Lösung: ```sql select id, (id % 3) as quality_control from products where quantity % 2 = 1 ``` ############################################################## ## The ROUND() Function Die Funktion `ROUND()` wird verwendet, um einen numerischen Wert auf eine bestimmte Anzahl von Nachkommastellen zu runden. Um die Funktion zu verwenden, folge dieser Syntax: ```sql ROUND(number, decimal_places) ``` - `number`: Die Zahl, die Sie runden möchten - `decimal_places`: (Optional) Die Anzahl der Nachkommastellen, auf die gerundet werden soll - Wenn weggelassen, wird auf die nächste ganze Zahl gerundet - Wenn positiv, wird auf so viele Nachkommastellen gerundet - Wenn negativ, wird links vom Dezimalpunkt gerundet Zum Beispiel einfaches Runden auf ganze Zahlen: ```sql SELECT ROUND(3.7);-- Returns 4.0SELECT ROUND(3.3);-- Returns 3.0SELECT ROUND(3.5);  -- Returns 4.0 (rounds up from .5) ``` **Hinweis:** Die `ROUND()`-Funktion in SQLite gibt immer einen Fließkommawert (REAL) zurück. Aus diesem Grund enthalten die obigen Ergebnisse ein Komma bzw. einen Dezimalpunkt (z. B. 4.0 statt 4). Runden auf bestimmte Nachkommastellen: ```sql SELECT ROUND(3.14159, 2);-- Returns 3.14SELECT ROUND(3.14159, 1);-- Returns 3.1SELECT ROUND(3.14159, 0);-- Returns 3.0SELECT ROUND(3.145, 2);-- Returns 3.15 (rounds up because the next digit is 5) ``` **Hinweis:** Wenn die `digit` nach der letzten verbleibenden Nachkommastelle 5 oder größer ist, `rounds` die letzte verbleibende Dezimalstelle auf. ############################################################## # Kurze SQL-Queries in MariaDB erfassen `SHOW PROCESSLIST` eignet sich **nicht**, um sehr kurze SQL-Statements zu erfassen. Diese sind häufig bereits beendet, bevor sie in der Prozessliste erscheinen. ## Aktuelle Konfiguration prüfen ### General Log Prüfen, ob das General Log aktiviert ist: SHOW VARIABLES LIKE 'general_log'; SHOW VARIABLES LIKE 'log_output' Oder beide Werte gemeinsam anzeigen: ```sql SHOW VARIABLES WHERE Variable_name IN ('general_log', 'log_output'); ``` Beispiel: | Variable_name | Value | | ------------- | ----- | | general_log | ON | | log_output | TABLE | --- ### Performance Schema Prüfen, ob das Performance Schema aktiviert ist: ```sql SHOW VARIABLES LIKE 'performance_schema'; ``` Zusätzlich prüfen, ob die Statement-Historie verfügbar ist: ```sql SHOW TABLES FROM performance_schema LIKE 'events_statements%'; ``` oder: ```sql SELECT COUNT(*) FROM performance_schema.events_statements_history; ``` --- ## General Log aktivieren > **Hinweis:** Das General Log erzeugt zusätzlichen Overhead und sollte nur für eine kurzfristige Analyse aktiviert werden. ```sql SET GLOBAL general_log = ON; SET GLOBAL log_output = 'TABLE'; ``` Abfragen anzeigen: ```sql SELECT event_time, user_host, argument FROM mysql.general_log WHERE command_type = 'Query' ORDER BY event_time DESC LIMIT 100; ``` General Log wieder deaktivieren: ```sql SET GLOBAL general_log = OFF; ``` --- ## Performance Schema verwenden (empfohlen) Falls das Performance Schema aktiviert ist, können ausgeführte Statements ohne das General Log analysiert werden: ```sql SELECT SQL_TEXT, TIMER_WAIT / 1000000000 AS duration_ms FROM performance_schema.events_statements_history ORDER BY EVENT_ID DESC; ``` Je nach Konfiguration kann auch die Tabelle `events_statements_history_long` verwendet werden. --- ## Slow Query Log Das Slow Query Log ist für sehr kurze Queries normalerweise ungeeignet. Es kann zwar so konfiguriert werden, dass alle Abfragen protokolliert werden: ```sql SET GLOBAL long_query_time = 0; ``` Für eine kurzfristige Analyse ist jedoch das **General Log** meist die bessere Wahl. --- ## Empfehlung | Ziel | Empfehlung | | ----------------------------------------------- | ----------------------- | | Alle SQL-Statements für kurze Zeit mitschneiden | General Log | | Regelmäßige Analyse mit geringem Overhead | Performance Schema | | Aktive, aktuell laufende Queries anzeigen | `SHOW FULL PROCESSLIST` | > **Fazit:** Für sehr kurze Queries ist `SHOW PROCESSLIST` ungeeignet. Verwende stattdessen das **General Log** oder – falls verfügbar – das **Performance Schema**. # Suche von Werten die in einer Spalte nur einmal vorkommem ```sql SELECT * FROM tabelle WHERE spalte IN ( SELECT spalte FROM tabelle GROUP BY spalte HAVING COUNT(*) = 1 ); ``` ###################################################### To change column names use the AS keyword: SELECT col1 AS firstColumn, col2 AS secondColumn FROM table1 The LIKE keyword is used to check string similarities with wildcards: % - means any number of characters _ - means exactly one character Common patterns: %a - ends with a a% - starts with a %a% - contains a _a% - a is the second character %a__ - a is in the 3rd from last place SELECT col1, col2, ... FROM table1 WHERE col1 LIKE '%a__' The BETWEEN operator provides a cleaner way to specify ranges instead of using >= and <=: WHERE col1 BETWEEN 5 AND 10 This is equivalent to: WHERE col1 >= 5 AND col1 <= 10 The BETWEEN operator is inclusive, meaning it includes the boundary values in the results. Use IN to check if a column matches any value from a list: SELECT * FROM table1 WHERE col1 IN ('a', 'b', 'c', 'd', 'e', 'f') This is equivalent to multiple OR conditions but much shorter. To limit the number of records returned by a query, use the LIMIT keyword: SELECT * FROM table1 LIMIT 10 This returns the top 10 records from the table. You can sort data by multiple columns using ORDER BY. The first column specified takes priority, and subsequent columns are used as tie-breakers: SELECT * FROM competition ORDER BY age DESC, avg_speed DESC This will: First sort by age in descending order If records have the same age, then sort by avg_speed in descending order Use ORDER BY to sort query results. By default, it sorts in ascending order: SELECT * FROM table_name ORDER BY column_name To specify sort direction, add ASC (ascending) or DESC (descending): ORDER BY column_name DESC ORDER BY column_name ASC Use IS NULL and IS NOT NULL to filter records based on missing values: SELECT * FROM table1 WHERE col1 IS NULL SELECT * FROM table1 WHERE col1 IS NOT NULL Boolean is a data type with two possible values: TRUE or FALSE. Examples: 10 > 100 - FALSE 10 > 5 - TRUE 10 > 5 AND 100 < 5 - FALSE Internally, TRUE is represented as 1 and FALSE is represented as 0. To filter data using booleans, use IS TRUE or IS NOT TRUE keywords: SELECT * FROM table1 WHERE col1 IS NOT FALSE AND col2 IS TRUE Use parentheses to control the order of operations when combining multiple conditions with AND and OR: WHERE age < 30 OR gender = 'female' AND age > 20 Returns all people under 30 (any gender) plus all females over 20. WHERE (age < 30 OR gender = 'female') AND age > 20 Returns only people over 20 who are either under 30 or female. Use AND, OR, and NOT keywords to create complex conditions in SQL queries: SELECT col1, col2 FROM table1 WHERE condition1 AND condition2 OR condition3 You can stack as many conditions as needed together using these logical operators. The NOT keyword is used to negate a condition, meaning we don't want the condition to be met. SELECT * FROM people WHERE NOT gender = 'male' The NOT keyword flips the condition. These queries are equivalent: WHERE age > 20 WHERE NOT age <= 20 The OR keyword returns records where at least one condition is true: SELECT * FROM people WHERE gender = 'female' OR age < 20 Returns rows where gender = 'female' or age < 20 (or both). The AND keyword requires both conditions to be true: SELECT * FROM people WHERE gender = "female" AND age < 20 This returns records where the person is female AND under 20 years old. Use the WHERE keyword to add conditions to your SQL queries: SELECT * FROM table_name WHERE column_name = 'value' For numeric comparisons: SELECT * FROM table_name WHERE column_name <= 20 Common comparison operators: =, <, >, <=, >= Use DISTINCT to get unique values from a column: SELECT DISTINCT column_name FROM table_name Without DISTINCT, duplicate values will be returned. With DISTINCT, each unique value appears only once in the result. In databases, rows are called records and columns are called fields. Use the asterisk * symbol to select all columns from a table: SELECT * FROM table_name Databases store data in organized tables with columns and rows. SQL (Structured Query Language) is used to manage and manipulate data in databases. To extract data from a database table, use the SELECT statement with the FROM clause: SELECT column1, column2, column3 FROM table_name ##################################################### Notizen bei Fehlersuche Hier sollen Werte aus eriner Tabelle in eine andere transferiert werden, jedoch es knallt: INSERT INTO isys_catg_sid_stid_list(custom_fields__data__id,isys_catg_sid_stid_list__isys_obj__id,isys_catg_sid_stid_list__sid,isys_catg_sid_stid_list__mm,isys_catg_sid_stid_list__rh,isys_catg_sid_stid_list__rha,isys_catg_sid_stid_list__status,isys_catg_sid_stid_list__description) #Wo ist der Fehler --> suchen SELECT isys_catg_custom_fields_list__data__id, isys_catg_custom_fields_list__isys_obj__id,CASE WHEN `sid`=-1 THEN NULL ELSE `sid` END, CASE WHEN `mm`=-1 THEN NULL ELSE `mm` END,CASE WHEN `rh`=-1 THEN NULL ELSE `rh` END,CASE WHEN `rha`=-1 THEN NULL ELSE `rha` END,`status`,`description` FROM ( SELECT isys_catg_custom_fields_list__data__id, isys_catg_custom_fields_list__isys_obj__id, MAX(CASE WHEN isys_catg_custom_fields_list__field_key = 'c_1465994230999' THEN isys_catg_custom_fields_list__field_content end) AS `sid`, MAX(CASE WHEN isys_catg_custom_fields_list__field_key = 'c_1465994236923' THEN isys_catg_custom_fields_list__field_content end) AS `mm`, MAX(CASE WHEN isys_catg_custom_fields_list__field_key = 'c_1519901667982' THEN isys_catg_custom_fields_list__field_content end) AS `rh`, MAX(CASE WHEN isys_catg_custom_fields_list__field_key = 'c_1603882415038' THEN isys_catg_custom_fields_list__field_content end) AS `rha`, MAX(CASE WHEN isys_catg_custom_fields_list__field_key LIKE 'C__CMDB__CAT__COMMENTARY%' THEN isys_catg_custom_fields_list__status END) AS `status`, MAX(CASE WHEN isys_catg_custom_fields_list__field_key LIKE 'C__CMDB__CAT__COMMENTARY%' THEN isys_catg_custom_fields_list__field_content END) AS `description` FROM isys_catg_custom_fields_list WHERE isys_catg_custom_fields_list__isysgui_catg_custom__id = 4 GROUP BY isys_catg_custom_fields_list__data__id) ref1 offset 247 rows fetch next 1 rows only; ## Hier knallt es INSERT INTO isys_catg_sid_stid_list(custom_fields__data__id,isys_catg_sid_stid_list__isys_obj__id,isys_catg_sid_stid_list__sid,isys_catg_sid_stid_list__mm,isys_catg_sid_stid_list__rh,isys_catg_sid_stid_list__rha,isys_catg_sid_stid_list__status,isys_catg_sid_stid_list__description) SELECT isys_catg_custom_fields_list__data__id, isys_catg_custom_fields_list__isys_obj__id,CASE WHEN `sid`=-1 THEN NULL ELSE `sid` END,CASE WHEN `mm`=-1 THEN NULL ELSE `mm` END,CASE WHEN `rh`=-1 THEN NULL ELSE `rh` END,CASE WHEN `rha`=-1 THEN NULL ELSE `rha` END,`status`,`description` FROM (SELECT isys_catg_custom_fields_list__data__id, isys_catg_custom_fields_list__isys_obj__id, MAX(CASE WHEN isys_catg_custom_fields_list__field_key = 'c_1465994230999' THEN isys_catg_custom_fields_list__field_content end) AS `sid`, MAX(CASE WHEN isys_catg_custom_fields_list__field_key = 'c_1465994236923' THEN isys_catg_custom_fields_list__field_content end) AS `mm`, MAX(CASE WHEN isys_catg_custom_fields_list__field_key = 'c_1519901667982' THEN isys_catg_custom_fields_list__field_content end) AS `rh`, MAX(CASE WHEN isys_catg_custom_fields_list__field_key = 'c_1603882415038' THEN isys_catg_custom_fields_list__field_content end) AS `rha`, MAX(CASE WHEN isys_catg_custom_fields_list__field_key LIKE 'C__CMDB__CAT__COMMENTARY%' THEN isys_catg_custom_fields_list__status END) AS `status`, MAX(CASE WHEN isys_catg_custom_fields_list__field_key LIKE 'C__CMDB__CAT__COMMENTARY%' THEN isys_catg_custom_fields_list__field_content END) AS `description` FROM isys_catg_custom_fields_list WHERE isys_catg_custom_fields_list__isysgui_catg_custom__id = 4 GROUP BY isys_catg_custom_fields_list__data__id )ref1 offset 247 rows fetch next 100 rows only; ############################################################## ## Recap - Parliamentary Election ### Challenge > Verfügbare Tabellen und Spalten: > > - `**ministers**`**:** `**seat**`**,** `**is_next_gov**`**,** `**is_spoke_bad**` Jeder Minister, der auf einem geraden nummerierten Sitz in der Regierung sitzt, gilt als „sicherer“ Minister. Ihre Aufgabe ist es, alle `seats` der „sicheren“ Minister zurückzugeben, die weiterhin in der nächsten Regierung dienen möchten, während Sie jeden Minister ausschließen, der ein schlechtes Wort gesprochen hat. Das Ergebnis sollte nur die relevanten Sitze enthalten. Bevor Sie mit der Lösung der Herausforderung beginnen, werfen Sie einen Blick auf die Tabellendaten. **Sie sind nicht sauber**. Die Spalten `is_next_gov` und `is_spoke_bad` enthalten Einsen und Nullen sowie auch yes's und no's. | ministers | | | | |:---------:| ---- | ----------- | ------------ | | | seat | is_next_gov | is_spoke_bad | | 1 | 1 | 0 | 0 | | 2 | 2 | 0 | 1 | | 3 | 3 | yes | no | | 4 | 4 | no | no | | 5 | 5 | 1 | no | | 6 | 6 | yes | no | | 7 | 7 | 1 | no | | 8 | 8 | 0 | yes | | 9 | 9 | 0 | 1 | | 10 | 10 | no | 1 | | 11 | 11 | yes | yes | | 12 | 12 | 1 | 1 | | 13 | 13 | 1 | 1 | | 14 | 14 | 1 | 1 | | 15 | 15 | yes | 0 | | 16 | 16 | 0 | 0 | | 17 | 17 | 0 | 0 | | 18 | 18 | 0 | no | | 19 | 19 | 1 | yes | | 20 | 20 | 1 | no | | 21 | 21 | 0 | 0 | | 22 | 22 | 1 | 0 | | 23 | 23 | yes | 1 | | 24 | 24 | yes | 1 | | 25 | 25 | no | yes | | 26 | 26 | 1 | no | | 27 | 27 | 0 | yes | | 28 | 28 | yes | no | | 29 | 29 | no | 0 | | 30 | 30 | yes | 0 | select seat from ministers where (seat % 2 = 0) and (is_spoke_bad = 0 or is_spoke_bad = 'no' )and (is_next_gov = 1 or is_next_gov = 'yes'); ############################################################## ## Recap - Police Criminal Arrest ### Challenge > Verfügbare Tabellen und Spalten: > > - `**police_report**`**:** `**name**`**,** `**report**`**,** `**map**`**,** `**severe_score**` Rufe die Namen der **5 schwersten Kriminellen** ab und sortiere sie nach `severe_score` in absteigender Reihenfolge Ein schwerer Krimineller ist jemand, der alle folgenden Kriterien erfüllt: - `report` ist entweder null oder `report` enthält einen der folgenden Buchstaben: `g`, `b`, `G` oder `B`. - `map` ist einer der folgenden Orte: `Caerleon`, `Dewsbury`, `Kirkwall`, `Findochty`. Benenne die Spalte als `worst_criminals`. | police_report | | | | | |:-------------:| ----------------- | ------ | ------------- | ------------ | | | name | report | map | severe_score | | 1 | Domingos Holden | VYyPJw | Lockinge | 2 | | 2 | Isabel Enid | | Findochty | 7 | | 3 | Tadgán Musa | FgDqud | Kara's Vale | 10 | | 4 | Filip Baxter | D1rJqH | Kirkwall | 3 | | 5 | Edorta Elias | pQ53RC | Dewsbury | 9 | | 6 | Kəmal Davy | BsI86j | Kara's Vale | 2 | | 7 | Isokrates Bituin | | Findochty | 5 | | 8 | Kassy Ramirus | Pkjv7J | Kirkwall | 7 | | 9 | Doris Blessing | 0kJXq1 | Dalmerlington | 6 | | 10 | Nedeljka Ganesh | EVe9ha | Kara's Vale | 8 | | 11 | Karlene Timotheus | 2HUBHz | Dewsbury | 7 | | 12 | Emerens Raman | PAGdHl | Findochty | 1 | | 13 | Mijo Ambrosios | | Luton | 5 | | 14 | Karlene Jairus | 4Z63Q5 | Dalmerlington | 8 | | 15 | Khordad Peter | | Findochty | 2 | | 16 | Biagio Mai | | Findochty | 9 | | 17 | Liwen Sigiward | B51ETs | Mansfield | 3 | | 18 | Svante Mona | DC0kGh | Caerleon | 5 | | 19 | Kshitija Ladislav | cSA0hA | Caerleon | 2 | | 20 | Ha-Eun Tatiana | YNYhHV | Kara's Vale | 4 | select name as worst_criminals from police_report where (report like '%g%' or report like '%b%' or report is null ) and map in ('Caerleon', 'Dewsbury', 'Kirkwall', 'Findochty') order by severe_score desc limit 5 ############################################################## ## Recap - Bar Beverage Container ### Challenge > Verfügbare Tabellen und Spalten: > > - `**beverages**`**:** `**id**`**,** `**current_year**`**,** `**expiration_year**` Ihre Bar lagert eine umfangreiche Auswahl an Säften, und Sie müssen feststellen, welche davon Aufmerksamkeit benötigen. Identifizieren und sortieren Sie diese Säfte basierend auf den folgenden klaren Kriterien: 1. `Old Expired Juices` 1. Säfte, deren Ablaufjahr MEHR als 6 Jahre vor dem aktuellen Jahr liegt (`current_year - expiration_year > 6`) 2. Diese müssen sofort recycelt werden 2. `Almost Expired Juices` 1. Säfte, die im aktuellen Jahr ablaufen 2. ODER Säfte, die nächstes Jahr ablaufen (`expiration_year = current_year + 1`) 3. Diese müssen zur Erneuerung geschickt werden Führen Sie diese Schritte aus: - Extrahieren Sie die IDs der Säfte, die eines dieser Kriterien erfüllen - Benennen Sie die ID-Spalte in 'to_renew' um - Sortieren Sie die Ergebnisse nach Bearbeitungs-Priorität: - Dringendste zuerst (älteste abgelaufene Säfte) - Dann fast abgelaufene Säfte - Verwenden Sie (current_year - expiration_year) zum Sortieren | beverages | | | | |:---------:| --- | ------------ | --------------- | | | id | current_year | expiration_year | | 1 | 145 | 2013 | 2014 | | 2 | 156 | 2001 | 2015 | | 3 | 167 | 2009 | 2004 | | 4 | 178 | 2005 | 2000 | | 5 | 124 | 2013 | 2006 | | 6 | 189 | 2002 | 2014 | | 7 | 198 | 2007 | 2013 | | 8 | 201 | 2004 | 2007 | | 9 | 206 | 2000 | 2000 | | 10 | 112 | 2011 | 2002 | | 11 | 209 | 2008 | 2004 | | 12 | 125 | 2015 | 2012 | | 13 | 980 | 2008 | 2005 | | 14 | 402 | 2010 | 2011 | | 15 | 391 | 2008 | 2009 | | 16 | 144 | 2015 | 2013 | | 17 | 213 | 2014 | 2007 | | 18 | 100 | 2001 | 2000 | | 19 | 145 | 2002 | 2004 | | 20 | 981 | 2011 | 2014 | | 21 | 210 | 2002 | 2007 | | 22 | 392 | 2010 | 2006 | | 23 | 393 | 2007 | 2013 | | 24 | 113 | 2010 | 2002 | | 25 | 255 | 2001 | 2008 | ```sql SELECT id as to_renew FROM beverages WHERE current_year - expiration_year > 6 OR current_year = expiration_year OR expiration_year = current_year + 1 ORDER by current_year-expiration_year DESC ``` ## Wiederholung – Neue Spalten erstellen ### Challenge > Verfügbare Tabellen und Spalten: > > - `items`**:** `id` Eine quartische Funktion ist definiert: ``` f(x) = ax4+bx3+cx2+dx+e ``` Definieren wir die konstanten Parameter: - `a = 3` - `b = 5` - `c = 0.9` - `d = 2.2` - `e = 1` Rufe die IDs und die quartische Funktion ab, wobei x die ID ist, und benenne die Spalte in `quartic` um. > Verwende keine integrierten Funktionen wie `POWER()`! Um die Potenz von 2 oder die Potenz von 3 zu berechnen, verwende das folgende Beispiel: ```sql a*a -- Potenz von 2 a*a*a -- Potenz von 3 ``` `select id , (3*id*id*id*id + 5*id*id*id + 0.9*id*id + 2.2 * id +1 )as quartic from items`