Oracle - 按Alpha数字排序

时间:2015-01-27 14:41:58

标签: sql oracle oracle11g

我需要通过包含varchar2 K-12的列来对结果集中的行进行排序。

示例:

ID Grade Expense
1 1 500
1 10 500
1 11 500
1 12 500
1 2 500
1 3 500
1 4 500
1 5 500
1 6 500
1 7 500
1 8 500
1 9 500
1 K 500
  

这是我的order by子句有效,但我希望有   将Grade = K作为结果集中每个ID的第一行。

order by ID, to_number(regexp_substr(grade, '^[[:digit:]]*'))
  

就目前而言,结果集中ID = K的行是最后一行而不是   第一。如何将其作为结果集中每个ID的第一行?

ID Grade Expense
1 K 500
1 1 500
1 2 500
1 3 500
1 4 500
1 5 500
1 6 500
1 7 500
1 8 500
1 9 500
1 10 500
1 11 500
1 12 500

提前致谢

4 个答案:

答案 0 :(得分:3)

只需使用case语句将K设置为低于1的值即可。如果您之后有Pre-K,则可以修改案例以便处理它。

With CTE as 
  (SELECT '1' as grade from dual union 
   SELECT '2' from dual union 
   select '10' from dual union 
   select 'K' from dual)
SELECT * FROM CTE 
ORDER BY CASE GRADE when 'K' then -1 
                    else to_number(regexp_substr(grade, '^[[:digit:]]*')) end

答案 1 :(得分:2)

这有点像kludge,但由于'K'的正则表达式返回null,请将顺序更改为:

order by ID, nvl(to_number(regexp_substr(grade, '^[[:digit:]]*')),0)

这将为'K'返回0并正确排序。

答案 2 :(得分:0)

仅以这种方式更改ORDER BY子句:

order by ID asc, decode(grade,'K',-1,grade) asc

答案 3 :(得分:0)

您可以执行以下操作:

WITH g1 AS (
  SELECT 1 AS id, TO_CHAR(level) AS grade, 500 AS expense FROM dual
 CONNECT BY level <= 12
   UNION
  SELECT 1, 'K', 500 FROM dual
   UNION
  SELECT 1, 'J', 500 FROM dual
)
SELECT g1.*, TO_NUMBER(REGEXP_SUBSTR(grade, '^\d+'))
     , DECODE(grade, 'K', -1, TO_NUMBER(REGEXP_SUBSTR(grade, '^\d+')))
  FROM g1
 ORDER BY DECODE(grade, 'K', -1, TO_NUMBER(REGEXP_SUBSTR(grade, '^\d+'))) NULLS LAST

在此查询中,我使用CONNECT BY来构建您的成绩表;当然你会想忽略那一部分。请注意,我为成绩级别添加了一个J的额外行。

在我的订单中,我正在使用DECODE(),因此如果grade = 'K',则会给出-1的值。对于任何可以转换为数字值的等级(即,如果它们以至少一个数字开头),我使用正则表达式来获取尽可能多的数字(您可以使用[:digit:][0-9]代替\d;但\d很好而且简短。)

我正在指定NULLS LAST,以便grade无法转换为K以外的数字的任何行都将是最后一行。

我包含额外的计算列只是为了让人们了解实际发生的事情以及如何生成值。查询不需要它们。

Please see SQL Fiddle demo here.