如何按 Oracle SQL IN() 子句中的值顺序对结果数据进行排序
Posted
技术标签:
【中文标题】如何按 Oracle SQL IN() 子句中的值顺序对结果数据进行排序【英文标题】:How to order the result data by the order of values in an Oracle SQL IN() clause 【发布时间】: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 中实现这一点?
【问题讨论】:
【参考方案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 列表,无需对您的查询进行其他修改。
【讨论】:
以上是关于如何按 Oracle SQL IN() 子句中的值顺序对结果数据进行排序的主要内容,如果未能解决你的问题,请参考以下文章
ORDER BY 子句“IN()”中指定的值,但在泛型 SQL 和 Informix 中