Im Grunde könnte man die Frage ausdehnen auf: "Wie erzeuge ich eine künstliche Sortierreihenfolge?". Aber zunächst einmal die Ausgangssituation. Betrachten wir einmal folgende Abfrage:
USE PUBS
GO
SELECT
title_id
, type
, price
, royalty
FROM
titles
ORDER BY
royalty
title_id type price royalty
-------- ------------ --------------------- -----------
MC3026 UNDECIDED NULL NULL
PC9999 popular_comp NULL NULL
PS1372 psychology 21.5900 10
BU1032 business 19.9900 10
BU1111 business 11.9500 10
BU7832 business 19.9900 10
PS2106 psychology 7.0000 10
PS3333 psychology 19.9900 10
PS7777 psychology 7.9900 10
TC3218 trad_cook 20.9500 10
PC8888 popular_comp 20.0000 10
TC7777 trad_cook 14.9900 10
MC2222 mod_cook 19.9900 12
PS2091 psychology 10.9500 12
TC4203 trad_cook 11.9500 14
PC1035 popular_comp 22.9500 16
MC3021 mod_cook 2.9900 24
BU2075 business 2.9900 24
(18 row(s) affected)
So, jetzt möchte man vielleicht aus irgendwelchen kosmetischen Gründen diejenigen Zeilen, die NULL in royalty stehen haben, nicht an Anfang seines Resultsets zeigen, sondern vielmehr am Ende. Aber wie? Der vielleicht naheliegenste Gedanken ist:
SELECT
title_id
, type
, price
, royalty
FROM
titles
ORDER BY
royalty DESC
title_id type price royalty
-------- ------------ --------------------- -----------
BU2075 business 2.9900 24
MC3021 mod_cook 2.9900 24
PC1035 popular_comp 22.9500 16
TC4203 trad_cook 11.9500 14
MC2222 mod_cook 19.9900 12
PS2091 psychology 10.9500 12
PS2106 psychology 7.0000 10
PS3333 psychology 19.9900 10
PS7777 psychology 7.9900 10
TC3218 trad_cook 20.9500 10
PS1372 psychology 21.5900 10
TC7777 trad_cook 14.9900 10
PC8888 popular_comp 20.0000 10
BU7832 business 19.9900 10
BU1032 business 19.9900 10
BU1111 business 11.9500 10
PC9999 popular_comp NULL NULL
MC3026 UNDECIDED NULL NULL
(18 row(s) affected)
Super, die NULLen stehen am Ende. Aber leider wird nun das ästhetische Empfinden gestört, daß die royalty nun leider mit den größten Wert beginnt und absteigend angezeigt wird. Eine einfache, und doch gleichzeitig effektive Lösung, liegt in folgendem Statement:
SELECT
title_id
, type
, price
, royalty
FROM
titles
ORDER BY
CASE WHEN royalty IS NULL THEN 1000 ELSE royalty END
title_id type price royalty
-------- ------------ --------------------- -----------
BU7832 business 19.9900 10
BU1032 business 19.9900 10
BU1111 business 11.9500 10
PC8888 popular_comp 20.0000 10
PS2106 psychology 7.0000 10
PS3333 psychology 19.9900 10
PS7777 psychology 7.9900 10
TC3218 trad_cook 20.9500 10
PS1372 psychology 21.5900 10
TC7777 trad_cook 14.9900 10
PS2091 psychology 10.9500 12
MC2222 mod_cook 19.9900 12
TC4203 trad_cook 11.9500 14
PC1035 popular_comp 22.9500 16
MC3021 mod_cook 2.9900 24
BU2075 business 2.9900 24
PC9999 popular_comp NULL NULL
MC3026 UNDECIDED NULL NULL
(18 row(s) affected)
Funktioniert einwandfrei, hat aber leider den Nachteil, daß man seine Werte für royalty genau kennen muß. Wählt man nämlich einen Wert (in diesem Beispiel 1000), für den es einen höheren Wert in royalty gibt, passiert folgendes:
SELECT
title_id
, type
, price
, royalty
FROM
titles
ORDER BY
CASE WHEN royalty IS NULL THEN 22 ELSE royalty END
title_id type price royalty
-------- ------------ --------------------- -----------
BU1032 business 19.9900 10
BU1111 business 11.9500 10
BU7832 business 19.9900 10
PC8888 popular_comp 20.0000 10
PS2106 psychology 7.0000 10
PS3333 psychology 19.9900 10
PS7777 psychology 7.9900 10
TC3218 trad_cook 20.9500 10
PS1372 psychology 21.5900 10
TC7777 trad_cook 14.9900 10
PS2091 psychology 10.9500 12
MC2222 mod_cook 19.9900 12
TC4203 trad_cook 11.9500 14
PC1035 popular_comp 22.9500 16
MC3026 UNDECIDED NULL NULL
PC9999 popular_comp NULL NULL
MC3021 mod_cook 2.9900 24
BU2075 business 2.9900 24
(18 row(s) affected)
was nun auch nicht wirklich weiterbringt. Eine gute Lösung bietet sich durch den Einsatz einer Variablen an. So, wie hier:
USE PUBS
GO
DECLARE @max_value INT
SELECT @max_value = MAX(royalty)+1 FROM titles
SELECT
title_id
, type
, price
, royalty
FROM
titles
ORDER BY
CASE WHEN royalty IS NULL THEN @max_value ELSE royalty END
title_id type price royalty
-------- ------------ --------------------- -----------
BU7832 business 19.9900 10
BU1032 business 19.9900 10
BU1111 business 11.9500 10
PC8888 popular_comp 20.0000 10
PS2106 psychology 7.0000 10
PS3333 psychology 19.9900 10
PS7777 psychology 7.9900 10
TC3218 trad_cook 20.9500 10
PS1372 psychology 21.5900 10
TC7777 trad_cook 14.9900 10
PS2091 psychology 10.9500 12
MC2222 mod_cook 19.9900 12
TC4203 trad_cook 11.9500 14
PC1035 popular_comp 22.9500 16
MC3021 mod_cook 2.9900 24
BU2075 business 2.9900 24
PC9999 popular_comp NULL NULL
MC3026 UNDECIDED NULL NULL
(18 row(s) affected)
Jetzt könnte man sich noch an dieser Extra Abfrage stoßen, die das Maximum ermittelt. Und diese noch zu eliminieren kann man folgendes machen:
SELECT
title_id
, type
, price
, royalty
FROM
titles
ORDER BY
CASE WHEN royalty IS NULL THEN 1 ELSE 0 END
, royalty
So, jetzt sollten alle zufrieden sein, und Marketing oder Vertriebsabteilungen können nun beruhigt weiter als Chartfabrik arbeiten.







