Bietet Rezepte, Lösungen und ausführliche Beispiele rund um gesundes SQL und zufriedene Datenbanken.
Manchmal kommen die Statistiker und Controller schon mit seltsamen Wünschen daher. Ich habe eine Tabelle mit zwei Spalten - eigentlich einfach - aber die Ausgabekriterien haben es in sich. Zudem soll das Ergebnis - aus Performancegründen - mit einem Query ermittelt werden.
* IBM DB2 9.1
* MySQL 5.1.30
* ORACLE 10g 10.2 EE
/**
* Die Tabelle
*/
CREATE TABLE test_order (
status INT NOT NULL,
datum DATE NOT NULL
);
/**
* Testdaten (MySQL, DB2)
*/
INSERT INTO test_order VALUES
( 0, '2010-12-01'),
( 0, '2010-12-02'),
( 0, '2010-12-03'),
( 1, '2010-12-01'),
( 1, '2010-12-02'),
( 1, '2010-12-03'),
( 1, '2010-12-04');
/**
* Testdaten (ORACLE)
*/
INSERT INTO test_order VALUES ( 0, TO_DATE('2010-12-01','YYYY-MM-DD'));
INSERT INTO test_order VALUES ( 0, TO_DATE('2010-12-02','YYYY-MM-DD'));
INSERT INTO test_order VALUES ( 0, TO_DATE('2010-12-03','YYYY-MM-DD'));
INSERT INTO test_order VALUES ( 1, TO_DATE('2010-12-01','YYYY-MM-DD'));
INSERT INTO test_order VALUES ( 1, TO_DATE('2010-12-02','YYYY-MM-DD'));
INSERT INTO test_order VALUES ( 1, TO_DATE('2010-12-03','YYYY-MM-DD'));
INSERT INTO test_order VALUES ( 1, TO_DATE('2010-12-04','YYYY-MM-DD'));
Die Daten sollen nach folgenden Kriterien sortiert werden:
1. Erst alle Einträge mit Status = 0 UND diese aufsteigend nach Datum
2. Dann alle Einträge mit Status = 1 UND diese absteigend nach Datum
Also eigentlich gegenläufige Sortierungen beim Datum und das Ganze mit einer SQL-Abfrage! Mit UNION läßt sich diese Aufgabe somit nicht lösen, da für die Teilabfragen im UNION keine eigenen Sortierungen erlaubt sind.
+--------+------------+
| status | datum |
+--------+------------+
| 0 | 2010-12-01 |
| 0 | 2010-12-02 |
| 0 | 2010-12-03 |
| 1 | 2010-12-04 |
| 1 | 2010-12-03 |
| 1 | 2010-12-02 |
| 1 | 2010-12-01 |
+--------+------------+
Mit einem doppelten CASE und ein bißchen NULL in der ORDER BY Klausel läßt sich auch so eine exotische Ausgabe erzeugen.
SELECT status, datum
FROM test_order
ORDER BY status,
CASE
WHEN status = 0 THEN datum
ELSE NULL
END ASC,
CASE
WHEN status = 1 THEN datum
ELSE NULL
END DESC;
+--------+------------+
| status | datum |
+--------+------------+
| 0 | 2010-12-01 |
| 0 | 2010-12-02 |
| 0 | 2010-12-03 |
| 1 | 2010-12-04 |
| 1 | 2010-12-03 |
| 1 | 2010-12-02 |
| 1 | 2010-12-01 |
+--------+------------+
Wie das obige Beispiel sehr anschaulich zeigt, kann mit dem CASE Befehl in der ORDER BY Klausel sehr raffinierte Sortierungen realisiert werden.