Hallo Bodo,
Gut, ich habe mir jetzt mal Gedanken gemacht, wie ich
- das Beispiel vereinfachen, dabei
- von der eigentlich zu lösenden Aufgabe entkoppeln, und dennoch
- das eigentlich zu lösende Problem beibehalten
kann.
ok, an Deinem Beispiel kann ich Dir weiterhelfen.
Das folgende in sich vollständige Beispiel zeigt, was ich prinzipiell haben will an einem konkreten Beispiel. Insbesondere zeigt es die in meinem zweiten Post genannte Kuriosität mit dem ORDER BY:
Nicht kurios, schlicht und einfach erwartungsgemäß. Du scheiterst immer noch an der Schlampigkeit von MySQL.
CREATE TABLE tabelle (n CHAR(1), s TINYINT, w DOUBLE);
INSERT INTO tabelle (n, s, w) VALUES
("a",1,3),("b",1,5),("c",0,2),("d",0,7),("e",0,4),("f",0,8);[code]
OK, eine Tabelle mit 6 Zeilen. Bis dahin ist noch alles richtig.
[code lang=sql]SELECT t1.n AS n1, t2.n AS n2, (t1.w-t2.w)(t1.w-t2.w) AS d
FROM tabelle AS t1, tabelle AS t2
HAVING d = (
SELECT MIN((t1.w-t3.w)(t1.w-t3.w))
FROM tabelle AS t3 WHERE t3.s=1
);
Nein, so nicht. Das Ergebnis ist leider mal wieder Zufall. Es sieht richtig aus, aber auch nicht mehr. Jedes andere mir bekannte Datenbankmanagementsystem weist Deine SQL-Statement als syntaktisch fehlerhaft zurück.
Du verwendest HAVING. Damit sieht es so aus, als könntest Du die berechnete Spalte d mit dem Spaltenalias zum Eingrenzen der Ergebnismenge benutzen. In Wirklichkeit sollte da eine WHERE-Klausel stehen. Nur ist es in dieser "dummerweise" nicht möglich, Spalten-Aliasnamen zu verwenden, wie ich heute [schon einmal](https://forum.selfhtml.org/?t=148901&m=966551) erwähnt habe.
Nun zu den Konsequenzen von HAVING:
[HAVING](http://dev.mysql.com/doc/refman/5.0/en/select.html#id3305657) impliziert, dass alle Spalten der Abfrage entweder eine Aggregatsfunktion aufweisen oder gruppiert werden. Du tust das nicht, somit sind die Werte schlicht und einfach mal wieder zufällig.
> // Liefert wie erwartet:
> // +------+------+------+
> // | n1 | n2 | d |
> // +------+------+------+
> // | a | a | 0 |
> // | c | a | 1 |
> // | e | a | 1 |
> // | b | b | 0 |
> // | d | b | 4 |
> // | e | b | 1 |
> // | f | b | 9 |
> // +------+------+------+
Dieses Ergebnis erreichst Du korrekt über folgendes Statement:
~~~sql
SELECT
t1.n AS n1,
t2.n AS n2,
(t1.w-t2.w)*(t1.w-t2.w) AS d
FROM
tabelle t1, -- nicht jeder SQL-Dialekt erlaubt AS für Tabellen-Aliasnamen
tabelle t2 -- deswegen lasse ich AS prinzipiell weg :-)
WHERE (t1.w-t2.w)*(t1.w-t2.w) = ( -- hier muss der gleiche Ausdruck hin, mit dem d berechnet wird
SELECT
MIN((t1.w-t3.w)*(t1.w-t3.w))
FROM tabelle t3
WHERE t3.s=1
)
Nun ist es auch ganz einfach, richtig zu sortieren. Dabei ist zu beachten, dass Du in der ORDER-BY-Klausel einen Spaltenalias verwenden darfst:
SELECT
t1.n AS n1,
t2.n AS n2,
(t1.w-t2.w)*(t1.w-t2.w) AS d
FROM
tabelle t1, -- nicht jeder SQL-Dialekt erlaubt AS für Tabellen-Aliasnamen
tabelle t2 -- deswegen lasse ich AS prinzipiell weg :-)
WHERE (t1.w-t2.w)*(t1.w-t2.w) = ( -- hier muss der gleiche Ausdruck hin, mit dem d berechnet wird
SELECT -- korrelierte Unterabfrage
MIN((t1.w-t3.w)*(t1.w-t3.w))
FROM tabelle t3
WHERE t3.s=1
)
ORDER BY d
liefert das von Dir gewünschte Ergebnis:
+------+------+------+
| n1 | n2 | d |
+------+------+------+
| a | a | 0 |
| b | b | 0 |
| c | a | 1 |
| e | a | 1 |
| e | b | 1 |
| d | b | 4 |
| f | b | 9 |
+------+------+------+
7 rows in set (0.00 sec)
Ich hoffe, Du kannst dieses Beispiel auf Deinen Bedarf hin extrapolieren.
Freundliche Grüße
Vinzenz