How Can I Make Oracle Query Sort Order Dynamic?

六眼飞鱼酱① 提交于 2019-12-02 06:51:44

You can use separate order by for asc and desc as following:

ORDER BY 
CASE pinSortOrder WHEN 'asc' THEN
    CASE pinSortColumn 
      WHEN 'FullName' THEN FULL_NAME 
      WHEN 'DateOfBirth' THEN to_char(DATE_OF_BIRTH,'yyyymmddhh24miss')
      WHEN 'Gender' THEN GEN_TR.GENDER   
    END
END,
CASE pinSortOrder WHEN 'desc' THEN
    CASE pinSortColumn 
      WHEN 'FullName' THEN FULL_NAME 
      WHEN 'DateOfBirth' THEN to_char(DATE_OF_BIRTH,'yyyymmddhh24miss')
      WHEN 'Gender' THEN GEN_TR.GENDER   
    END
END DESC

Let's say you have passed pinSortColumn as FullName and pinSortOrder as asc then order by clause will be ORDER BY FULL_NAME, NULL DESC (please note that default order will be asc so I have not write it in the code. Query will be ordered by FULL_NAME in ascending manner)

Now, If you have passed pinSortColumn as FullName and pinSortOrder as desc then order by clause will be ORDER BY NULL, FULL_NAME DESC.

Null will not impact ordering.

I hope it is clear now.

Cheers!!

Try this one:

WHERE ...
ORDER BY 
   CASE pinSortColumn 
      WHEN 'FullName' THEN FULL_NAME 
      WHEN 'DateOfBirth' THEN DATE_OF_BIRTH
      WHEN 'Gender' THEN GEN_TR.GENDER   
   END;

However, I don't think you can use ASC, DESC is this way. You to create a dynamic query. For an OPEN ... FOR ... statement it is trivial:

sqlstr := 'SELECT * FROM (
      SELECT EMPLOYEE_ID, USERNAME, FULL_NAME, DATE_OF_BIRTH, EMP.GENDER_ID, GEN_TR.GENDER, EMP.WORK_TYPE_ID, WT_TR.WORK_TYPE, SALARY, EMAIL, PROFILE_IMAGE,
      ROW_NUMBER() OVER (ORDER BY EMPLOYEE_ID ASC) RN

      FROM EMPLOYEES EMP
      INNER JOIN GENDERS GEN ON EMP.GENDER_ID = GEN.GENDER_ID
      LEFT JOIN GENDERS_MLD GEN_TR ON GEN.GENDER_ID = GEN_TR.GENDER_ID AND GEN_TR.LANGUAGE = :pinLanguage
      INNER JOIN WORK_TYPES WT ON EMP.WORK_TYPE_ID = WT.WORK_TYPE_ID
      LEFT JOIN WORK_TYPES_MLD WT_TR ON WT.WORK_TYPE_ID = WT_TR.WORK_TYPE_ID AND WT_TR.LANGUAGE = :pinLanguage
    )
    WHERE RN BETWEEN (((:pinPage - 1) * :pinPageSize) + 1) AND (:pinPage * :pinPageSize) 
    ORDER BY '

CASE pinSortColumn 
   WHEN 'FullName' THEN sqlstr := sqlstr || 'FULL_NAME ';
   WHEN 'DateOfBirth' THEN sqlstr := sqlstr || 'DATE_OF_BIRTH ';
   WHEN 'Gender' THEN sqlstr := sqlstr || 'GEN_TR.GENDER ';
END CASE;   
sqlstr := sqlstr || pinSortOrder;

OPEN poutEmployeeCursor FOR sqlstr USING pinLanguage, pinLanguage, pinPage, pinPageSize, pinPage, pinPageSize;

Not in case you run Oracle 12c or newer you can use the Row Limiting Clause instead of dealing with row number.

You can avoid all these duplicated cases. Multiply row number by -1 when descending order is required:

order by 
    case pinSortOrder when 'desc' then -1 else 1 end * 
    row_number() over (
      order by case pinSortColumn when 'FullName'    then full_name     end, 
               case pinSortColumn when 'Gender'      then gender        end, 
               case pinSortColumn when 'DateOfBirth' then date_of_birth end)  

dbfiddle demo

Also this way you do not have to convert data the same type, no need to use to_char.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!