Oracle
 sql >> Database >  >> RDS >> Oracle

Ordine condizionale per clausola

Questo sembra essere il bug 5695629, che sembra essere stato sollevato contro 10g e non sembra essere stato ancora risolto (a partire da 12cR2; non ho ancora 18 con cui giocare), il che è insolito.

Puoi evitarlo racchiudendo la query in una selezione esterna prima di ordinare:

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 ;

Ma come name e marks sono (presumibilmente) diversi tipi di dati - stringa e numero - che invece riceveranno

Potresti convertire marks a una stringa, ma se lo fai, devi riempirla in modo che l'ordinamento alfabetico della stringa risultante corrisponda ancora all'ordine numerico - disordinato ma plausibile poiché i segni possono (di nuovo, presumibilmente - se è una percentuale?) essere solo fino a tre cifre :

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<>demo violino utilizzando alcuni dati fittizi forniti tramite CTE.

Se i segni possono essere più di tre cifre, modificare la maschera del formato in modo che corrisponda alla lunghezza massima possibile.

Il TO_CHAR('NULL') la parte è anche strana in quanto ti darà la stringa letterale "NULL" nella colonna del nome per quelle righe. Poiché inizi con una stringa letterale TO_CHAR() la parte è inutile, basta usare 'NULL' AS name direttamente. Se vuoi che sia vuoto, puoi semplicemente usare null AS name e corrisponderà al tipo di dati dell'espressione della colonna corrispondente dal primo ramo dell'unione (e prenderà anche il suo alias). Puoi eseguire il cast in modo esplicito su un tipo di stringa, ad es. cast(null as varchar2(20)) AS name ma non sembra avere molto senso.