Oracle
 sql >> Base de données >  >> RDS >> Oracle

Ordre conditionnel par clause

Cela semble être le bogue 5695629, qui semble avoir été soulevé contre 10g et ne semble pas encore avoir été corrigé (à partir de 12cR2 ; je n'ai pas encore 18 pour jouer avec), ce qui est inhabituel.

Vous pouvez l'éviter en enveloppant la requête dans une sélection externe avant de commander :

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 ;

Mais en tant que name et marks sont (vraisemblablement) des types de données différents - chaîne et nombre - qui obtiendront à la place

Vous pouvez convertir des marks à une chaîne, mais si vous le faites, vous devez le remplir afin que le tri alphabétique de la chaîne résultante corresponde toujours à l'ordre numérique - désordonné mais plausible puisque les marques ne peuvent (encore une fois, probablement - s'il s'agit d'un pourcentage ?) que jusqu'à trois chiffres :

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<>démo de violon en utilisant des données factices fournies via les CTE.

Si les marques peuvent comporter plus de trois chiffres, modifiez le masque de format pour qu'il corresponde à la longueur maximale possible.

Le TO_CHAR('NULL') part est également impair car cela vous donnera la chaîne littérale "NULL" dans la colonne de nom pour ces lignes. Puisque vous commencez avec un littéral de chaîne, le TO_CHAR() la partie est inutile, utilisez simplement 'NULL' AS name directement. Si vous voulez réellement qu'il soit vide, vous pouvez simplement utiliser null AS name et il correspondra au type de données de l'expression de colonne correspondante de la première branche de l'union (et récupérera également son alias). Vous pouvez convertir explicitement en un type de chaîne, par exemple. cast(null as varchar2(20)) AS name mais cela ne semble pas être très utile.