Spaß mit MySQL ;-)

akretschmer

Datenbank-Guru
Beiträge
10.307
Code:
mysql> select * from demo;
+------+------+
| c  | val  |
+------+------+
| a  |  10 |
| b  |  10 |
| a  |  20 |
| c  |  30 |
+------+------+
4 rows in set (0.00 sec)

mysql> select c, max(val) from (select * from demo order by c asc) bla;
+------+----------+
| c  | max(val) |
+------+----------+
| a  |  30 |
+------+----------+
1 row in set (0.01 sec)

mysql> select c, max(val) from (select * from demo order by c desc) bla;
+------+----------+
| c  | max(val) |
+------+----------+
| c  |  30 |
+------+----------+
1 row in set (0.01 sec)

Lach und weg...
 
Werbung:
Naja das ist schon nachvollziehbar. Auch wenn es die SQL Syntax verletzt, eigentlich nichts anderes als:
Code:
SELECT    max(val),
        (    SELECT    TOP 1 t.c
            FROM    demo t
            WHERE    t.val = demo.val
            ORDER BY t.c ASC )
FROM    demo
Natürlich ist es scheisse wenn man sagen wir einen GROUP BY machen will und vergisst ihn anzugeben. Andererseits ist es reproduzierbar und damit nur eine art Hack der SQL Spezifikation um schnell mal eben "Beispieldaten" von c zu bekommen.
 
Naja das ist schon nachvollziehbar. Auch wenn es die SQL Syntax verletzt, eigentlich nichts anderes als:
...
Natürlich ist es scheisse wenn man sagen wir einen GROUP BY machen will und vergisst ihn anzugeben. Andererseits ist es reproduzierbar und damit nur eine art Hack der SQL Spezifikation ...

Das Problem ist komplexer.

MySQL erlaubt das weglassen von GROUP BY. Klarer Verstoß gegen die SQL-Spec. In meinem Beispiel habe ich das Subselect mit einem ORDER BY gemacht, um zu zeigen, daß unterschiedliche Reihenfolge unterschiedliche Resultate bringt. Wenn ich das ORDER BY weglasse steht es der DB frei, die Daten in beliebiger Reihenfolge zu liefern. Die Reihenfolge der Daten in der Tabelle ist ja nicht definiert, und die physische Reihenfolge kann sich durch UPDATE eines Datensatzes auch ändern. Auch kann durch Optimierungen in kommenden Versionen es dazu kommen, daß die Reihenfolge sich ändert (Siehe PG mit synchroniserten parallen Scans, Details dazu auf Nachfrage). Das innere Select kann auch komplexer sein oder ein ORDER BY RAND haben, betrachte das innere Select einfach mal als 'Blackbox'.

Die Folge ist also: ich muß damit rechnen, bei jedem Aufruf ein unterschiedliches Resultat zu bekommen. Toll!
 
Das ist bedingt richtig. Natürlich steht es der DB frei, in welcher Reihenfolge sie Ergebnisse ohne ORDER BY liefert. Ich behaupte aber ohne Änderung am Datenbestand wird sie es bei der selben Abfrage immer in der selben Reihenfolge tun. Außerdem geht es hier ja eher darum einen beliebigen Wert zu wählen, manchmal (wenn auch selten) will man genau das erreichen.

Mir wäre auch eine entsprechende Funktion und ein korrektes GROUP BY als Pflichtangabe lieber (gemäß Spec). Das Verhalten von MySQL ist hier aber "nachvollziehbar", wenn auch nicht Regelkonform.

ORDER BY rand() wird übrigens die Sortierung nicht verändern denn rand() liefert für jede Spalte den selben Wert zurück und wird nicht für jede Zeile neu erzeugt (das nervt mich wirklich^^).
 
Das ist bedingt richtig. Natürlich steht es der DB frei, in welcher Reihenfolge sie Ergebnisse ohne ORDER BY liefert. Ich behaupte aber ohne Änderung am Datenbestand wird sie es bei der selben Abfrage immer in der selben Reihenfolge tun.

Darauf sollte man sich nicht verlassen. In PG ist es so, daß wenn Client a ein select * ohne ORDER BY macht, dann wird die Table sequentiell gelesen. Wenn der z.B. zu 50% fertig ist und Client b macht auch ein select * ohne ORDER BY auf dieselbe Tabelle, dann optimiert PG: Client b bekommt den Stream von a, der ja in der Hälfte ist, mitgeliefert. Wenn a fertig ist, bekommt b den 'vorderen' Teil der Tabelle. Ist eine Optimierung seit 8.2 oder 8.3 oder so, weiß nicht mehr genau. a bekommt die Daten also in physische Reihenfolge, b bekommt den hinteren Teil zuerst und dann den vorderen Teil - also in unterschiedlicher Sortierung

Fazit: ohne Änderung der Daten bekommen 2 Clients dieselben Daten in unterschiedlicher Reihenfolge. Kannst Du Dir sicher sein, daß MySQL in der nächsten Version nicht auch diese Optimierung einbaut?


ORDER BY rand() wird übrigens die Sortierung nicht verändern denn rand() liefert für jede Spalte den selben Wert zurück und wird nicht für jede Zeile neu erzeugt (das nervt mich wirklich^^).

Code:
mysql> select c, max(val) from (select * from demo order by rand()) bla;
+------+----------+
| c  | max(val) |
+------+----------+
| b  |  30 |
+------+----------+
1 row in set (0.01 sec)

mysql> select c, max(val) from (select * from demo order by rand()) bla;
+------+----------+
| c  | max(val) |
+------+----------+
| a  |  30 |
+------+----------+
1 row in set (0.01 sec)

mysql> select c, max(val) from (select * from demo order by rand()) bla;
+------+----------+
| c  | max(val) |
+------+----------+
| b  |  30 |
+------+----------+
1 row in set (0.00 sec)

Wie gesagt, betrachte das innere Select als Blackbox. Oder als VIEW, oder als eine Funktion, die Du nicht kennst, die Du nur nutzt.

Ich find das einfach nur FAIL.
 
Ich behaupte aber ohne Änderung am Datenbestand wird sie es bei der selben Abfrage immer in der selben Reihenfolge tun.

Und ich behaupte. dass eine Menge keine Liste ist. Selbst wenn deine Aussage empirisch belegbar ist widerspricht sie der Definition.

ORDER BY rand() wird übrigens die Sortierung nicht verändern denn rand() liefert für jede Spalte den selben Wert zurück und wird nicht für jede Zeile neu erzeugt (das nervt mich wirklich^^).
Code:
SELECT *, random() AS r
FROM [table]
ORDER BY r
Das funktioniert in SQLite, PostgreSQL und sogar MySQL.
 
Selbst wenn deine Aussage empirisch belegbar ist widerspricht sie der Definition.
Letzteres will ich nicht in Frage stellen aber das Ergebnis ist (wenn auch mit Einschränkungen), vorhersehbar.

MSSQL:

Code:
SELECT    rand(),
        pk
FROM    tabelle
0,793012462750625 D9B29E63-5501-2B41-8757-126C8BA77027
0,793012462750625 4C887DA3-9B79-6644-B386-1D6E0626EE8A
0,793012462750625 5BB8F511-5025-2049-AE3E-20447458C5E8
0,793012462750625 2B1B0D04-425F-6345-8557-271F8E3C4B6D
0,793012462750625 6BB4C01A-60EE-A742-B072-4A80E0BC7A22
Ich hab jetzt mal angenommen das ist überall so.
 
Werbung:
Jo extrem unpraktisch, ist mir auch schon aufgefallen. Da ist newid() einfacher als Basis für zufällige Zeichenketten.
 
Zurück
Oben