简体   繁体   中英

How to make conditional order by statement with multiple data types, sql oracle?

I tried to do so, but my data types are char and date

select * from table_name   
    where
    smthng 
    order by  
    case when to_date(to_char( :edate, 'dd.mm.yyyy'),'dd.mm.yyyy')-
    to_date(to_char( :sdate, 'dd.mm.yyyy'),'dd.mm.yyyy')>0  
    then ddate   
    else  department end

You don't need any conversion for substraction considering :edate and :sdate are of type date

select *
  from table_name
 where smthng
 order by case
            when :edate - :sdate > 0 then
             to_char(ddate ,'dd.mm.yyyy')
            else
             department
            end

The value in order must match the data type so if you need can't return date or string but a single data type only A8ssuming department is a strint data type you should convert data as char)

select * 
from table_name   
where .......   smthng .... 
order by  
  case when to_date(to_char( :edate, 'dd.mm.yyyy'),'dd.mm.yyyy')-
    to_date(to_char( :sdate, 'dd.mm.yyyy'),'dd.mm.yyyy')>0  
    then to_char(ddate ,    'dd.mm.yyyy')
 else  department
  end

All the outputs from a CASE statement must have the same data-type and since you can't convert department to a DATE data-type then you will need to convert ddate to a String or else have two CASE statements with mutually exclusive conditions.

Some additional points:

  • Firstly, you don't need to convert :sdate and :edate from a DATE data type to a string and then back to a DATE ; just perform the comparison on the DATE s.
  • Secondly, as you are doing this in the ORDER BY clause then you need to make sure what you are ordering by makes sense. Ordering by a date formatted as a 'dd.mm.yyyy' string does not make sense as it will perform an alpha-numeric string comparison and not a comparison in ascending date order. If you do want to use a single case statement and convert both to strings then use an ISO 8601 format YYYY-MM-DD which will let you order the formatted date string using an alpha-numberic sort.

Like this:

SELECT *
FROM   table_name
WHERE  something
ORDER BY
       CASE
       WHEN :edate > :sdate
       THEN TO_CHAR( ddate ,'YYYY-MM-DD' )
       ELSE department
       END

or you can just use 2 CASE statements, one for each mutually exclusive case and defaulting each to NULL (or some other constant) when it does not match:

SELECT *
FROM   table_name
WHERE  something
ORDER BY
       CASE WHEN :edate > :sdate THEN ddate ELSE NULL       END,
       CASE WHEN :edate > :sdate THEN NULL  ELSE department END;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM