Die Division mit Literalen in MySQL (Die Division mit Literalen in MySQL), Lektion, Seite 723266
https://www.purl.org/stefan_ram/pub/literaldivision_sql (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram

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

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram723266 stefan_ram:723266 Die Division mit Literalen in MySQL Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd723266, slrprddef723266, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/literaldivision_sql