通过从中读取数值来对字段进行排序

时间:2014-04-27 05:43:10

标签: sql oracle sorting sql-order-by numeric

我有一个场景,其中一个字段包含字符和数字,我想按下面给出的排序。

City 1 City 2 City 3 City 4a City 4b City 4c City 10 City 11a City 11b Town 1 Town 2 Town 3a Town 4b Town 10

该查询还应考虑到将来可以添加更多字段,例如100101a等。

提前致谢。

2 个答案:

答案 0 :(得分:1)

另一种可能的方法是使用正则表达式
下面是一个如何解析字符串并分成子字段的示例:

select col,
    regexp_replace( col, '\D+\s+(\d+).*','\1') As field1,
    regexp_replace( col, '\D+\s+\d+(\D*),*.*','\1') As field2,
    regexp_replace( col, '\D+\s+\d+\D*,*(\d*)','\1') As field3
from table1
ORDER BY field1, field2, field3
; 

如果只需要排序,则在ORDER BY子句中使用这些函数:

select * from table1
order by
    regexp_replace( col, '\D+\s+(\d+).*','\1'),
    regexp_replace( col, '\D+\s+\d+(\D*),*.*','\1'),
    regexp_replace( col, '\D+\s+\d+\D*,*(\d*)','\1')

演示:http://sqlfiddle.com/#!4/8f289/4

但是对于大型数据集来说,这将是非常缓慢的 您需要规范化表中的数据 - 在插入期间解析它并将每个字段存储在表中的单独列中,然后在这些列上创建索引。


使用强制转换为数字的排序:

select col,
    cast( regexp_replace( col, '\D+\s+(\d+).*','\1') as numeric) As field1,
    regexp_replace( col, '\D+\s+\d+(\D*),*.*','\1')  As field2,
    cast( regexp_replace( col, '\D+\s+\d+\D*,*(\d*)','\1') As numeric) As field3
from table1
ORDER BY field1, field2, field3
;

select * from table1
order by
    cast( regexp_replace( col, '\D+\s+(\d+).*','\1') as numeric),
    regexp_replace( col, '\D+\s+\d+(\D*),*.*','\1'),
    cast( regexp_replace( col, '\D+\s+\d+\D*,*(\d*)','\1') As numeric)

演示:http://sqlfiddle.com/#!4/8f289/10

答案 1 :(得分:0)

怎么样:

order by SUBSTRING(col_name, CHARINDEX(' ', col_name) + 1, len(col_name)-(CHARINDEX(' ', col_name)-1))

这里SUBSTRING(col_name, from_index, till_index)给我这些索引之间的子串,并使用CHARINDEX函数我找到字符串第二个字周围的索引来提取它。

请注意,根据我的理解,这不会使用任何索引,如果表中有大量数据,可能会很慢。