How Can I Make Oracle Query Sort Order Dynamic?

后端 未结 3 2019
你的背包
你的背包 2021-01-23 17:23

I have a Oracle procedure inside a package like this

PROCEDURE getEmployee
(
  pinLanguage               IN    VARCHAR2,
  pinPage                   IN    NUMBER         


        
相关标签:
3条回答
  • 2021-01-23 18:07

    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.

    0 讨论(0)
  • 2021-01-23 18:08

    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.

    0 讨论(0)
  • 2021-01-23 18:10

    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!!

    0 讨论(0)
提交回复
热议问题