在Oracle中按自定义顺序对列进行排序时遇到问题。
我需要列中的特定行首先出现,然后剩下的项目应按字母顺序排在下面。该列有一个以字母,数字和特殊字符开头的数据..每当我尝试按ASC对列进行排序时,它首先返回我的特殊字符,首先是数字,然后是字母。
例如结果集
ACCOUNT_NAME
-------------
First Row
Second Row
Third Row
Fourth Row
Fifth Row
$Specialchar Row
4Number Row
Alpha Row
以下顺序的预期结果
ACCOUNT_NAME
-------------
First Row
Alpha Row
Fifth Row
Fourth Row
Second Row
Third Row
4Number Row
$Specialchar Row
我已尝试执行以下查询,但似乎无法正常工作
SELECT ACCOUNT_NAME FROM ACCOUNT
ORDER BY decode(ACCOUNT_NAME,'First Row',1),
regexp_substr(UPPER(ACCOUNT_NAME), '^[a-zA-Z]') ASC;
答案 0 :(得分:2)
如果我理解得很好,你想以这种方式订购:
如果是这样,您可以使用案例来构建要在订单中使用的值:
/* sample data */
with example(ACCOUNT_NAME) as (
select 'First Row' from dual union all
select 'Second Row' from dual union all
select 'Third Row' from dual union all
select 'Fourth Row' from dual union all
select 'Fifth Row' from dual union all
select '$Specialchar Row' from dual union all
select '4Number Row' from dual union all
select 'Alpha Row' from dual
)
/* query */
select *
from example
order by case
when account_name = 'First Row' then 1
when regexp_like(account_name, '^[A-Za-z]') then 2
when regexp_like(account_name, '^[0-9]') then 3
else 4
end,
account_name
工作原理:
select case
when account_name = 'First Row' then 1
when regexp_like(account_name, '^[A-Za-z]') then 2
when regexp_like(account_name, '^[0-9]') then 3
else 4
end as orderByValue,
account_name
from example
order by case
when account_name = 'First Row' then 1
when regexp_like(account_name, '^[A-Za-z]') then 2
when regexp_like(account_name, '^[0-9]') then 3
else 4
end,
account_name
给出:
ORDERBYVALUE ACCOUNT_NAME
------------ ----------------
1 First Row
2 Alpha Row
2 Fifth Row
2 Fourth Row
2 Second Row
2 Third Row
3 4Number Row
4 $Specialchar Row
答案 1 :(得分:0)
我认为ASCII功能可以解决您的问题。但是很容易根据值的第一个字符进行排序。 例如。 'AA'将在'11'之前出现,它将在'$$'之前出现。但是'A $'将出现在'A4'之前,除非您将程序扩展到所有角色,否则它将在'AA'之前出现。扩展这一点非常烦人。
所以代码如下。
WITH data_set AS
(SELECT '001' emp_id, 'aaa' emp_name, '005' mgr_id
FROM DUAL
UNION
SELECT '005' emp_id, 'bbb' emp_name, '010' mgr_id
FROM DUAL
UNION
SELECT '010' emp_id, 'ccc' emp_name, '050' mgr_id
FROM DUAL
UNION
SELECT '020' emp_id, '4xy' emp_name, '050' mgr_id
FROM DUAL
UNION
SELECT '050' emp_id, '$52' emp_name, '100' mgr_id
FROM DUAL
UNION
SELECT '100' emp_id, '555' emp_name, '200' mgr_id
FROM DUAL
UNION
SELECT '200' emp_id, '@$' emp_name, NULL mgr_id
FROM DUAL)
SELECT emp_name,
CASE
WHEN (ASCII (emp_name) BETWEEN 65 AND 90)
OR (ASCII (emp_name) BETWEEN 97 AND 122)
THEN 1
WHEN ASCII (emp_name) BETWEEN 48 AND 57
THEN 2
ELSE 3
END val
FROM data_set
ORDER BY val;