Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Bedingte Reihenfolge nach Klausel

Dies scheint Fehler 5695629 zu sein, der anscheinend gegen 10g ausgelöst und noch nicht behoben wurde (Stand 12cR2; ich habe noch keine 18 zum Spielen), was ungewöhnlich ist.

Sie können dies vermeiden, indem Sie die Abfrage vor dem Sortieren in eine äußere Auswahl einschließen:

select name, grade, marks
from
(
    SELECT
        name, grade, marks
    FROM
        students, grades
    WHERE
        min_mark <= marks
        AND   marks <= max_mark
        AND   marks >= 70
    UNION
    SELECT
        TO_CHAR('NULL') AS name, grade, marks
    FROM
        students, grades
    WHERE
        min_mark <= marks
        AND   marks <= max_mark
        AND   marks <= 69
)
order by grade desc,case when grade >= 1 
                     then  name 
                     when grade < 1 
                     then  marks
                     end ;

Aber als name und marks sind (vermutlich) unterschiedliche Datentypen - Zeichenfolge und Zahl - die stattdessen erhalten werden

Sie könnten marks umwandeln zu einer Zeichenfolge, aber wenn Sie dies tun, müssen Sie sie auffüllen, damit die alphabetische Sortierung der resultierenden Zeichenfolge immer noch mit der numerischen Reihenfolge übereinstimmt - chaotisch, aber plausibel, da die Markierungen (wieder vermutlich - wenn es sich um einen Prozentsatz handelt?) nur bis zu drei Ziffern betragen können :

select name, grade, marks
from
(
    ...
    <the main part of your query here as a subquery, as above>
    ...
)
order by grade desc,case when grade >= 8 
                     then  name 
                     when grade < 8 
                     then  to_char(marks, 'FM000')
                     end ;

db<>Fiddle-Demo unter Verwendung einiger Dummy-Daten, die über CTEs geliefert werden.

Wenn die Markierungen mehr als drei Stellen haben können, ändern Sie die Formatmaske, um sie an die maximal mögliche Länge anzupassen.

Der TO_CHAR('NULL') Teil ist auch ungerade, da Sie dadurch die wörtliche Zeichenfolge "NULL" in der Namensspalte für diese Zeilen erhalten. Da Sie mit einem String-Literal beginnen, ist TO_CHAR() Teil ist sinnlos, verwenden Sie einfach 'NULL' AS name direkt. Wenn Sie tatsächlich möchten, dass es leer ist, können Sie einfach null AS name verwenden und es stimmt mit dem Datentyp des übereinstimmenden Spaltenausdrucks aus dem ersten Zweig der Union überein (und übernimmt auch seinen Alias). Sie könnten explizit in einen Zeichenfolgentyp umwandeln, z. cast(null as varchar2(20)) AS name aber es scheint nicht viel Sinn zu machen.