Oracle自定义排序无法正常工作

时间:2017-06-07 07:28:43

标签: sql database oracle

在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;

2 个答案:

答案 0 :(得分:2)

如果我理解得很好,你想以这种方式订购:

  1. 硬编码值首先出现
  2. 以字母开头的字符串,按字母顺序排列
  3. 以数字
  4. 开头的字符串
  5. 然后是所有其他字符串,基于ASCII值
  6. 如果是这样,您可以使用案例来构建要在订单中使用的值:

    /* 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;