Die Division mit Literalen in SQL (MySQL )
Vorbereitung
Zum Nachvollziehen der folgenden Beispiele kann das folgende Skript in einen MySQL-Klienten kopiert werden.
- Skript (MySQL )
WARNINGS; SET sql_mode = 'ANSI,TRADITIONAL';
DROP SCHEMA IF EXISTS D; CREATE SCHEMA D; USE D;CREATE TABLE UMSATZ ( JAHR INTEGER, OST INTEGER, WEST INTEGER );
INSERT INTO UMSATZ ( JAHR, OST, WEST )VALUES( 2025, 1424, 4228 );
INSERT INTO UMSATZ ( JAHR, OST, WEST )VALUES( 2026, 733, 2891 );
INSERT INTO UMSATZ ( JAHR, OST, WEST )VALUES( 2027, 126, 561 );
INSERT INTO UMSATZ ( JAHR, OST, WEST )VALUES( 2028, 78, 121 );CREATE TABLE ONE ( COL INTEGER );
INSERT INTO ONE ( COL ) VALUES ( 1 );SELECT * FROM UMSATZ;
SELECT * FROM ONE;
Division mit Literalwerten
Um eine Division auszuwerten, muß nicht unbedingt erst eine Basistabelle angelegt werden. Falls kein Wert aus einer Tabelle ausgelesen werden muß, kann die Division auch einfach nur mit Numeralia geschrieben werden, wie das folgende Beispiel zeigt.
- Konsole
SELECT 1 / 2;
+--------+
| 1 / 2 |
+--------+
| 0.5000 |
+--------+
Zur Information schreiben wir in diesem Kurs den Datentyp von Ausdrücken einer Tabelle manchmal in symbolischer Schreibweise rechts neben die Tabelle. Dies wird aber von MySQL nicht so ausgegeben, sondern nur hier manuell hinzugefügt.
Beim Typ »int(1)« ist die Zahl in den Klammern nicht wirklich Bestandteil des Typs, sondern gibt nur eine Empfehlung für die Anzeigebreite bei der Ausgabe eines Wertes wieder. Diese Zahl kann im wesentlichen ignoriert werden. Egal, ob »int(1)« oder »int(9)« – der Wertbereich von ist immer der selbe, er geht von −2147483648 (einschließlich) bis 2147483647 (einschließlich).
Beim Typ »decimal(5,4)« gibt »5« die gesamte Anzahl aller Stellen an (1 bis 65) und »4« die Anzahl der Nachkommastellen (0 bis 30).
- Konsole
SELECT 1 / 2;
+--------+
| 1 / 2 | int(1) / int(1)
+--------+
| 0.5000 | decimal(5,4)
+--------+
Wie bereits in einer früheren Lektion erklärt wurde, ist es laut SQL-Standard und bei manchen Datenbanksystem nötig, pro forma eine Basistabelle anzugeben, die dann genau eine Zeile enthalten sollte. Bei MySQL ist dies aber nicht notwendig.
- Konsole
SELECT 1 / 2;
+--------+
| 1 / 2 |
+--------+
| 0.5000 |
+--------+
Assoziativität
Das folgende Beispiel zeigt die Assoziativität der Division: Die Division ist linksassoziativ. Das heißt, daß »1 / 2 / 3« als »( 1 / 2 )/ 3« interpretiert wird.
- Konsole
SELECT 1 / 2 / 3;
+------------+
| 1 / 2 / 3 |
+------------+
| 0.16666667 |
+------------+
Das folgende Beispiel zeigt dieselbe Berechnung wie das vorangegangene Beispiel.
- Konsole
SELECT ( 1 / 2 )/ 3;
+--------------+
| ( 1 / 2 )/ 3 |
+--------------+
| 0.16666667 |
+--------------+
In »1 / 2 / 3« ist der Quotient »1 / 2« ein Teilausdruck, der Text »2 / 3« gilt darin aber nicht als ein Ausdruck (Teilausdruck).
Kombinationen mit Klammern
Falls »2 / 3« als ein Ausdruck angesehen werden soll, so kann dies durch Einklammern klargestellt werden. Dann wird zuerst »2 / 3« berechnet und anschließend der Kehrwert davon.
- Konsole
SELECT 1 /( 2 / 3 );
+--------------+
| 1 /( 2 / 3 ) |
+--------------+
| 1.5000 |
+--------------+
Kombinationen mit »-«
Es ist auch möglich, die beiden Operatoren »-« und »/« gemeinsam in einem Ausdruck zu verwenden. Da die Priorität des Vorzeichenoperators »-« größer ist als die des Divisionsoperators »/« wird in dem Ausdruck »-3 / 2« der Text »-3« als ein Ausdruck angesehen und nicht »3 / 2«.
- Konsole
SELECT -3 / 2;
+---------+
| -3 / 2 | int(2) / int(1)
+---------+
| -1.5000 | decimal(5,4)
+---------+
Prioritäten
In der folgenden Liste von Operatoren stehen Operatoren höherer Priorität weiter oben.
- Prioritäten von Operatoren
- »-«, »+« (Vorzeichen)
- »/«
Operatoren
Der Begriff „Operator“ wurde zunächst in Zusammenhang mit genau einem Operanden definiert, ein Operator kann auch auch mehrere Operanden haben. Entsprechend erweitern wir hier die Definition des Begriffs Operator dahingehend, daß ein Operator nicht unbedingt genau einen Operanden haben muß (wie bei den Vorzeichen), sondern auch mehrere Operanden haben kann (wie bei der Division, wo es zwei Operanden gibt).
Anzahl der Nachkommastellen
Die Division fügt vier Nachkommastellen zur Anzahl der Nachkommastellen ihres ersten Operanden hinzu.
- Konsole
SELECT 1.00000000000000000000000000 / 7;
+----------------------------------+
| 1.00000000000000000000000000 / 7 | decimal(27,26) / int(1)
+----------------------------------+
| 0.142857142857142857142857142857 | decimal(31,30)
+----------------------------------+SELECT 1 / 7;
+--------+
| 1 / 7 |
+--------+
| 0.1429 |
+--------+SELECT 1 / 1;
+--------+
| 1 / 1 |
+--------+
| 1.0000 |
+--------+SELECT 1 / 1 / 1;
+------------+
| 1 / 1 / 1 |
+------------+
| 1.00000000 |
+------------+SELECT 1 / 1 / 1 / 1;
+----------------+
| 1 / 1 / 1 / 1 |
+----------------+
| 1.000000000000 |
+----------------+
Division mit dem Datentyp »double«
Bei Verwendung des Datentyps »double« verläuft zunächst alles wie erwartet.
- Konsole
SELECT 1E0/3E0;
+--------------------+
| 1E0/3E0 | double / double
+--------------------+
| 0.3333333333333333 | double
+--------------------+
Das folgende Beispiel zeigt jedoch eine überraschende Abweichung vom offensichtlichen Ergebnis »3«.
- Konsole
SELECT 0.3e0 / 0.1e0;
+--------------------+
| 0.3e0 / 0.1e0 |
+--------------------+
| 2.9999999999999996 |
+--------------------+
Die Abweichung kommt dadurch zustande, daß der Datentyp »double« die Werte der Operanden im Binärsystem darstellt und sie dort nur näherungsweise darstellen kann. Deswegen ist das Ergebnis auch nur näherungsweise richtig. Die relative Abweichung (prozentuale Abweichung) des Ergebnisses vom richtigen Ergebnis ist aber sehr klein. Daher ist das Ergebnis für technische Anwendungen ausreichend genau. Es ist eher ein kosmetisches Problem, wenn der Wert solch eine geringe Abweichung hat. Dieses kosmetische Problem könnte man durch Runden verdecken (Runden wird später behandelt werden). Es ist auch möglich, einen Datentyp zu verwenden, der kurze Dezimalnumerale genau speichern kann, wie den Datentyp »DECIMAL«; dieser liefert dann das richtige Ergebnis, braucht aber mehr Speicherplatz und wird langsamer verarbeitet als »DOUBLE«.
- Konsole
SELECT 0.3 / 0.1;
+-----------+
| 0.3 / 0.1 |
+-----------+
| 3.00000 |
+-----------+
Daß der Typ, wie hier gezeigt, das Ergebnis einer Rechnung beeinflussen kann, verdeutlicht, daß es manchmal wichtig sein kann, den Typ von Ausdrücken zu kennen.
Division mit Spaltenwerten und Literalwerten
Umsatz von Tausend Taler in einfache Taler umrechnen.
- Konsole
SELECT JAHR, OST FROM UMSATZ;
+------+------+
| JAHR | OST |
+------+------+
| 2025 | 1424 |
| 2026 | 733 |
| 2027 | 126 |
| 2028 | 78 |
+------+------+SELECT JAHR, OST / 0.001 FROM UMSATZ;
+------+--------------+
| JAHR | OST / 0.001 |
+------+--------------+
| 2025 | 1424000.0000 |
| 2026 | 733000.0000 |
| 2027 | 126000.0000 |
| 2028 | 78000.0000 |
+------+--------------+SELECT JAHR, OST, WEST FROM UMSATZ;
+------+------+------+
| JAHR | OST | WEST |
+------+------+------+
| 2025 | 1424 | 4228 |
| 2026 | 733 | 2891 |
| 2027 | 126 | 561 |
| 2028 | 78 | 121 |
+------+------+------+SELECT JAHR, OST / 0.001, WEST / 0.001 FROM UMSATZ;
+------+--------------+--------------+
| JAHR | OST / 0.001 | WEST / 0.001 |
+------+--------------+--------------+
| 2025 | 1424000.0000 | 4228000.0000 |
| 2026 | 733000.0000 | 2891000.0000 |
| 2027 | 126000.0000 | 561000.0000 |
| 2028 | 78000.0000 | 121000.0000 |
+------+--------------+--------------+
Quotient in Prozent umrechnen.
- Konsole
SELECT JAHR, OST / WEST FROM UMSATZ;
+------+-------------+
| JAHR | OST / WEST |
+------+-------------+
| 2025 | 0.3368 |
| 2026 | 0.2535 |
| 2027 | 0.2246 |
| 2028 | 0.6446 |
+------+-------------+SELECT JAHR, OST / WEST / 0.01 FROM UMSATZ;
+------+-------------------+
| JAHR | OST / WEST / 0.01 |
+------+-------------------+
| 2025 | 33.68022700 |
| 2026 | 25.35454850 |
| 2027 | 22.45989300 |
| 2028 | 64.46280990 |
+------+-------------------+
Der DIV-Operator
Der DIV-Operator erlaubt eine ganzzahlige Division, bei welcher das Ergebnis einen INT-Typ hat. Das Ergebnis kann man erhalten indem man zunächst eine normale Division ausführt und dann die Nachkommastellen abschneidet. So ergibt »7/4« zunächst »1.7500«; daraus enthält man durch Abschneiden der Nachkommastellen dann »1«.
- Konsole
SELECT 0 DIV 4, 1 DIV 4, 2 DIV 4, 3 DIV 4;
+---------+---------+---------+---------+
| 0 DIV 4 | 1 DIV 4 | 2 DIV 4 | 3 DIV 4 |
+---------+---------+---------+---------+
| 0 | 0 | 0 | 0 |
+---------+---------+---------+---------+SELECT 4 DIV 4, 5 DIV 4, 6 DIV 4, 7 DIV 4;
+---------+---------+---------+---------+
| 4 DIV 4 | 5 DIV 4 | 6 DIV 4 | 7 DIV 4 |
+---------+---------+---------+---------+
| 1 | 1 | 1 | 1 |
+---------+---------+---------+---------+
Mit »DIV 4« kann man beispielsweise die Frage beantworten, wie viele Viererkartons man füllen kann, wenn man eine gegeben Anzahl von Stücken hat. Mit sieben Stücken kann man beispielsweise einen Viererkarton füllen, die verbleibenden drei Stücke reichen nicht mehr aus, um einen weiteren Karton zu füllen.
Abschneiden der Nachkommastellen
Die Division durch »1« kann verwendet werden, um einen Wert nach »INT« zu wandeln, und die Nachkommastellen abzuschneiden
- Konsole
SELECT 3 DIV 1, 3.2 DIV 1, 3.8 DIV 1, -3.2 DIV 1, -3.7 DIV 1;
+---------+-----------+-----------+------------+------------+
| 3 DIV 1 | 3.2 DIV 1 | 3.8 DIV 1 | -3.2 DIV 1 | -3.7 DIV 1 |
+---------+-----------+-----------+------------+------------+
| 3 | 3 | 3 | -3 | -3 |
+---------+-----------+-----------+------------+------------+
Allgemeines zum Divisionsoperator
Das Zeichen »/« wird „Schrägstrich“ genannt.
Die Division ist linksassoziativ.
Die Priorität des Vorzeichenoperators ist höher als die des Divisionsoperators.
Syntax
- Ausdruck (Syntaxdiagramm, vereinfacht)
Ausdruck (vereinfacht)
.-------------.
----.------------->| Spaltenname |--------------.--->
| '-------------' |
| .-------------. |
'------------->| Literal |--------------'
| '-------------' |
| .-. .-------------. |
'----->( + )-->| Ausdruck |--------------'
| '-' '-------------' |
| .-. .-------------. |
'----->( - )-->| Ausdruck |--------------'
| '-' '-------------' |
| .-. .-------------. .-. |
'----->( ( )-->| Ausdruck |--->( ) )-----'
| '-' '-------------' '-' |
| .----------. .-. .----------. |
'-->| Ausdruck |--->( / )--->| Ausdruck |---'
| '----------' '-' '----------' |
| .----------. .---. .----------. |
'-->| Ausdruck |-->( DIV )-->| Ausdruck |---'
'----------' '---' '----------'
Sind D und d zwei Ausdrücke, so ist D /d wieder ein Ausdruck, der Quotient von D und d. Dabei wird D auch Dividend und d Divisor (diˈviːzoːʌ̯) genannt: „Dividend/Divisor“. (Diese vereinfachte Syntax bringt die Assoziativität der Division nicht richtig zum Ausdruck. Diese wird daher weiter unten separat erklärt.) Dieser Operator hat zwei Operandenausdrücke (einen linken und einen rechten). Er wird daher binär genannt, während die zuvor vorgestellten Operatoren unär waren (sie hatten nur einen Operandenausdruck). Dieser Operator steht zwischen seinen Operandenausdrücken, daher wird er auch als ein Infixoperator bezeichnet.
Typanforderungen
Der Dividend und der Divisor müssen beide jeweils als Zahlenenwert interpretierbar sein sein.
Typregeln (Auszug)
- Typregeln (Auszug)
DECIMAL(A,B)/DECIMAL(C,D)=DECIMAL(A+C+div_precision_increment-1?,B+div_precision_increment)
DECIMAL/DOUBLE = DOUBLE
DOUBLE/DECIMAL = DOUBLE
INT/INT=DECIMAL
INT/DOUBLE=DOUBLE
DOUBLE/INT=DOUBLE
DOUBLE/DOUBLE=DOUBLE
Man kann sagen, daß das Ergebnis einer Division normalerweise den Typ »DECIMAL« hat, nur wenn einer der beiden Operanden den Typ »DOUBLE« hat, dann ist es »DOUBLE«.
Die Anzahl der Nachkommastellen ergibt sich aus der Anzahl der Nachkommastellen des Zählers plus dem Wert der Variablen »div_precision_increment«, die normalerweise 4 ist und eigentlich »div_scale_increment« heißen müßte, da die Anzahl der Nachkommastellen auf englisch »SCALE« genannt wird.
Die Anzahl der gesamten Stellen des Ergebnisses ist vermutlich die Summe der Anzahl der Stellen der Operanden plus »div_precision_increment« minus 1. Diese Information ist nicht so gut dokumentiert, wird aber auch selten benötigt.
Das folgende Kommando würde »div_precision_increment« für die aktuelle Sitzung auf »30« setzen.
- Konsole
SET div_precision_increment = 30;
Zur Vereinfachung haben wir hier nur einen Auszug der Typregeln angegeben. Später wird erklärt werden, wie der Leser bei Bedarf die Typen von Ausdrücken selber ermitteln kann. So kann der Leser dann bei Bedarf auch den Typ weiterer Typen von Quotienten ermitteln. Insbesondere ist es auch wieder erlaubt, mit VARCHAR-Werten zu rechnen, dies wird aber nicht empfohlen.
Übungsfragen
? Division
Welchen Wert erwarten Sie in der Tabelle »SELECT 2/1;«?
? Division (1)
Welchen Wert erwarten Sie in der Tabelle »SELECT 2/2;«?
? Division (2)
Welchen Wert erwarten Sie in der Tabelle »SELECT 1/2;«?
? Division (3)
Welche drei Werte erwarten Sie als Ergebnis der letzten Eingabe des folgenden Transskripts an Stelle der drei Fragezeichen?
- Konsole
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; SET sql_mode = "ANSI,TRADITIONAL";
SET div_precision_increment = 0;
DROP SCHEMA IF EXISTS D; CREATE SCHEMA D; USE D;CREATE TABLE T ( I INT );
INSERT INTO T ( I )VALUES( 2 );
INSERT INTO T ( I )VALUES( 4 );
INSERT INTO T ( I )VALUES( 8 );SELECT I FROM T;
+------+
| I |
+------+
| 2 |
| 4 |
| 8 |
+------+SELECT I/2 FROM T;
+------+
| I |
+------+
| ? |
| ? |
| ? |
+------+
Übungsaufgaben
/ Division
Die folgende Tabelle »FORMAT« enthält die Höhe verschiedener Papierformate in Millimetern. Ergänzen Sie, was an Stelle der drei Punkte »...« in der letzten Benutzereingabe stehen muß, damit sich die Ausgabe mit der Spalte »CMHOEHE« ergibt, welche die entsprechenden Werte in Zentimetern enthält!
- Skript (MySQL )
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; SET sql_mode = "ANSI,TRADITIONAL";
SET div_precision_increment = 0;
DROP SCHEMA IF EXISTS D; CREATE SCHEMA D; USE D;CREATE TABLE FORMAT ( NAME VARCHAR( 255 ), MMHOEHE INT );
INSERT INTO FORMAT ( NAME, MMHOEHE )VALUES( 'X4', 220 );
INSERT INTO FORMAT ( NAME, MMHOEHE )VALUES( 'X3', 440 );
INSERT INTO FORMAT ( NAME, MMHOEHE )VALUES( 'X2', 880 );
INSERT INTO FORMAT ( NAME, MMHOEHE )VALUES( 'X1', 1760 );SELECT * FROM FORMAT;
+------+---------+
| NAME | MMHOEHE |
+------+---------+
| X4 | 220 |
| X3 | 440 |
| X2 | 880 |
| X1 | 1760 |
+------+---------+SELECT ... FROM FORMAT;
+------+---------+
| NAME | CMHOEHE |
+------+---------+
| X4 | 22 |
| X3 | 44 |
| X2 | 88 |
| X1 | 176 |
+------+---------+
Reserveaufgaben
/ Division
Diese Reserveaufgabe sollte erst nach der Nachbesprechung der vorherigen Übungsaufgabe bearbeitet werden, falls es bei der Bearbeitung der vorherigen Übungsaufgabe noch Probleme gab.
Die folgende Tabelle »DAUER« enthält Angaben aus einer Studien, die beschreiben, wie lange die getesten Geräte im Dauerbetrieb arbeiteten. Die Angaben wurden in Stunden abgespeichert. Ergänzen Sie, was an Stelle der drei Punkte »...« in der letzten Benutzereingabe stehen muß, damit sich die Ausgabe mit der Spalte »DDAUER« ergibt, welche die entsprechenden Werte in Tagen enthält!
- Skript (MySQL )
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; SET sql_mode = "ANSI,TRADITIONAL";
SET div_precision_increment = 0;
DROP SCHEMA IF EXISTS D; CREATE SCHEMA D; USE D;CREATE TABLE GERAETETEST ( NAME VARCHAR( 255 ), HDAUER INT );
INSERT INTO GERAETETEST ( NAME, HDAUER )VALUES( 'Kappa X-2000', 960 );
INSERT INTO GERAETETEST ( NAME, HDAUER )VALUES( 'Miranda Wunder', 492 );
INSERT INTO GERAETETEST ( NAME, HDAUER )VALUES( 'Excelsior Star', 204 );
INSERT INTO GERAETETEST ( NAME, HDAUER )VALUES( 'Chromium 500', 732 );SELECT * FROM GERAETETEST;
+----------------+--------+
| NAME | HDAUER |
+----------------+--------+
| Kappa X-2000 | 960 |
| Miranda Wunder | 492 |
| Excelsior Star | 204 |
| Chromium 500 | 732 |
+----------------+--------+SELECT ... FROM GERAETETEST;
+----------------+--------+
| NAME | DDAUER |
+----------------+--------+
| Kappa X-2000 | 80 |
| Miranda Wunder | 41 |
| Excelsior Star | 17 |
| Chromium 500 | 61 |
+----------------+--------+
Zitat *
- 9075-2 7.12 (Entwurf 2010, vereinfacht)
- <term> ::= <factor> | <term> <solidus> <factor>
- <factor> ::= [ <sign> ] <numeric primary>
- <numeric primary> ::= <left paren> <value expression> <right paren> | <unsigned literal>> | <column reference>
- <column reference> ::= <basic identifier chain>
- <basic identifier chain> ::= <identifier chain>
- <identifier chain> ::= <identifier> [ { <period> <identifier> }... ]
Quellen *
Auf den folgenden Webseiten finden sich einige Informationen zu den hier behandelten arithmetischen Operatoren. Zum Verständnis dieses Kurses ist es jedoch nicht notwendig, diese Webseite jetzt aufzusuchen. Sie können aber zum Nachschlagen bei weiterführenden Fragen herangezogen werden.
- URI
http://dev.mysql.com/doc/refman/5.0/en/arithmetic-functions.html
http://dev.mysql.com/doc/refman/5.0/en/precision-math-examples.html