【问题标题】:How to order the result data by the order of values in an Oracle SQL IN() clause如何按 Oracle SQL IN() 子句中的值顺序对结果数据进行排序
【发布时间】:2016-12-19 10:46:28
【问题描述】:

当 SQL 返回结果时,我们需要按照将值传递给 SQL 的 IN() 子句的确切顺序对它们进行排序。

查询和结果:(HR 架构)

select EMPLOYEE_ID, FIRST_NAME
from EMPLOYEES
where EMPLOYEE_ID in ('151','149','145','147','155');

EMPLOYEE_ID FIRST_NAME         
----------- --------------------
        145 John                
        147 Alberto             
        149 Eleni               
        151 David               
        155 Oliver              

但我们需要它们按 '151','149','145','147','155' 的顺序排列

预期输出

EMPLOYEE_ID FIRST_NAME         
----------- --------------------
        151 David               
        149 Eleni               
        145 John                
        147 Alberto             
        155 Oliver              

在 MySQL 中,有 FIELD() 函数。 如何在 Oracle 中实现这一点?

【问题讨论】:

    标签: sql oracle sql-order-by


    【解决方案1】:

    在 Oracle 中,您可以在 PL/SQL 中编写自己的字段函数,也可以使用标准 SQL 的CASE WHEN

    select EMPLOYEE_ID, FIRST_NAME
    from EMPLOYEES
    where EMPLOYEE_ID in ('151','149','145','147','155')
    order by case EMPLOYEE_ID 
      when '151' then 1
      when '149' then 2
      when '145' then 3
      when '147' then 4
      when '155' then 5;
    

    这是一个派生表的替代方案:

    select EMPLOYEES.EMPLOYEE_ID, EMPLOYEES.FIRST_NAME
    from EMPLOYEES
    join
    (
      select '151' as EMPLOYEE_ID, 1 as POS from DUAL
      union all
      select '149' as EMPLOYEE_ID, 2 as POS from DUAL
      union all
      select '145' as EMPLOYEE_ID, 3 as POS from DUAL
      union all
      select '147' as EMPLOYEE_ID, 4 as POS from DUAL
      union all
      select '155' as EMPLOYEE_ID, 5 as POS from DUAL
    ) IDS ON IDS.EMPLOYEE_ID = EMPLOYEES.EMPLOYEE_ID
    order by IDS.POS;
    

    【讨论】:

      【解决方案2】:

      假设列表中的值是唯一的

      select      e.EMPLOYEE_ID,e.FIRST_NAME
      
      from                EMPLOYEES e
      
                  join    (select  rownum as n,column_value as EMPLOYEE_ID 
                           from    table (SYS.ODCIVARCHAR2LIST ('151','149','145','147','155')) t
                          ) t  
      
                  on      t.EMPLOYEE_ID =
                          e.EMPLOYEE_ID
      
      order by    t.n
      

      +-------------+------------+
      | EMPLOYEE_ID | FIRST_NAME |
      +-------------+------------+
      | 151         | David      |
      +-------------+------------+
      | 149         | Eleni      |
      +-------------+------------+
      | 145         | John       |
      +-------------+------------+
      | 147         | Alberto    |
      +-------------+------------+
      | 155         | Oliver     |
      +-------------+------------+
      

      【讨论】:

        【解决方案3】:

        一种方法可能是使用提供顺序的属性来构建您的列表,并将其与您的表一起用于 JOIN。 例如:

        with yourList(EMPLOYEE_ID, position) as (
            select '151', 1 from dual union all
            select '149', 2 from dual union all
            select '145', 3 from dual union all
            select '147', 4 from dual union all
            select '155', 5 from dual
        )
        select EMPLOYEE_ID, FIRST_NAME
        from EMPLOYEES inner join yourList using(EMPLOYEE_ID)
        order by position;
        

        如果您想在列表更改时限制要编写的代码,您可以通过拆分字符串来构建您的列表:

        with yourList(EMPLOYEE_ID, position) as (
            SELECT regexp_substr(stringList, '[^,]+', 1, level), level
              FROM (select '151,149,145,147,155' as stringList from dual)
              CONNECT BY instr(stringList, ',', 1, level - 1) > 0
        )
        select EMPLOYEE_ID, FIRST_NAME
        from EMPLOYEES inner join yourList using(EMPLOYEE_ID)
        order by position;
        

        通过这种方式,您只需编辑您的 ID 列表,无需对您的查询进行其他修改。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-09-28
          • 2012-02-15
          • 2012-04-30
          • 1970-01-01
          • 2020-11-05
          • 1970-01-01
          • 2010-10-27
          相关资源
          最近更新 更多