具有多个列的order by子句,用于排序不同的情况

时间:2016-02-26 05:54:07

标签: oracle sorting sql-order-by

Student details table

- 如果我错了或者有更多的优化方式来实现它,请纠正我

- 要在多列上订购,您可以使用此方法,但不正确,因为

- 解码函数中的第一列将列的其余部分视为自己的相同数据类型

- 所以当它出现在日期并标记它将分类为var-char而不是数字,分别为日期

- 如果第一列是数字,则会将该列的其余部分视为数字并通过错误

- ORA-00932:不一致的数据类型:预期NUMBER得到DATE

select 
   roll_number,
   admission_date,
   student_name,
   total_marks,
   progress
from 
   student_details
order by 
   case when upper(:dir) = 'ASC' then
      decode(:sort, 
         'student_name', student_name,
         'roll_number', roll_number, 
         'admission_date', admission_date, 
         'total_marks', total_marks,
         'progress', progress
      ) 
   end asc, 
   case when upper(:dir) = 'DESC' then
      decode(:sort, 
         'student_name', student_name,
         'roll_number', roll_number, 
         'admission_date', admission_date, 
         'total_marks', total_marks,
         'progress', progress
      ) 
   end desc;

- 要实现正确的多个order by子句,您需要为每个列使用多个case

- 或者至少针对每个常见的数据类型列

select 
   roll_number,
   admission_date,
   student_name,
   total_marks,
   progress
from 
   student_details
order by 
   case when upper(:dir) = 'ASC' and :sort = 'student_name' then 
      student_name 
   end asc, 
   case when upper(:dir) = 'ASC' and :sort = 'roll_number' then 
      roll_number 
   end asc,
   case when upper(:dir) = 'ASC' and :sort = 'admission_date' then 
      admission_date 
   end asc,
   case when upper(:dir) = 'ASC' and :sort = 'total_marks' then 
      total_marks 
   end asc,
   case when upper(:dir) = 'ASC' and :sort = 'progress' then 
      progress 
   end asc,
   case when upper(:dir) = 'DESC' and :sort = 'student_name' then 
      student_name 
   end desc,
   case when upper(:dir) = 'DESC' and :sort = 'roll_number' then 
      roll_number 
   end desc,
   case when upper(:dir) = 'DESC' and :sort = 'admission_date' then 
      admission_date 
   end desc,
   case when upper(:dir) = 'DESC' and :sort = 'total_marks' then 
      total_marks 
   end desc,
   case when upper(:dir) = 'DESC' and :sort = 'progress' then 
      progress 
   end desc;

1 个答案:

答案 0 :(得分:1)

您的观察结果似乎是正确的。有一种方法可以缩短这种语法:

select *
  from (
    select * from students_details 
      order by case :sort when 'roll_number'    then roll_number end, 
               case :sort when 'admission_date' then admission_date end,
               case :sort when 'student_name'   then student_name end )
  order by rownum * decode(:dir, 'DESC', -1, 1)

最后一行很重要,如果你希望它下降,它会恢复排序。

来源文章:CASE in ORDER BY statement(其中一条评论)。