Question

I have a scenario where a field contains both character and number, I am suppose to sort it as given below.

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

The query should also take into account that in future more fields can be added like 100, 101a, etc.

Thanks in advance.

Was it helpful?

Solution

Another possible approach is using regular expressions.

Here is an example how to parse a string and divide in into subfields:

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
; 

If only a sort is required, then use these functions in ORDER BY clause:

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')

Demo: http://sqlfiddle.com/#!4/8f289/4

But for large dataset this will be horrible slow.
You need to normalize data in the table - parse it during insertion and store each field in separate column in the table, then create an index on these columns.


A sort using a cast to numeric:

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)

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

OTHER TIPS

How about:

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

Here SUBSTRING(col_name, from_index, till_index) gives me substring between these indexes, and using CHARINDEX function I am finding indexes around second word of the string to extract it.

Please note, as par my understanding this will not use any index and can be slow if you have large data in the table.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top