Reputation: 1807
I'm using Oracle database and now I would like to sort my data that contains text and number.
Script for below data:
SELECT * FROM WA_GA_TBL_LINES
WHERE LINENAME LIKE 'LEGO%' AND
SECTIONID_FK = 'SC0013' AND
LINENAME != 'LEGO 16'
ORDER BY LPAD(LINENAME,
(SELECT MAX(LENGTH(LINENAME))
FROM WA_GA_TBL_LINES)) ASC
Data
LEGO 1
LEGO 2
LEGO 3
LEGO 4
LEGO 5
LEGO 6
LEGO 7
LEGO 8
LEGO 9
LEGO 10
LEGO 11
LEGO 15
LEGO 12A
LEGO 12B
LEGO 13A
LEGO 13B
LEGO 14A
LEGO 14B
As you can see LEGO 15
is not in the correct position.
What I want is LEGO 15
is on the last position (due to 15 is most high number)
LEGO 1
LEGO 2
LEGO 3
LEGO 4
LEGO 5
LEGO 6
LEGO 7
LEGO 8
LEGO 9
LEGO 10
LEGO 11
LEGO 12A
LEGO 12B
LEGO 13A
LEGO 13B
LEGO 14A
LEGO 14B
LEGO 15
Upvotes: 2
Views: 92
Reputation: 142720
First of all, I'm not criticizing anyone; this is just another view, viewed over the first cup of coffee today. I also hope that it won't be nonsense.
Note that answers posted so far presume that the first word is always "LEGO". Well, based on sample data, it really is. Only the @OP knows the truth so I'm also only guessing, just like you, guys.
However, if that's so, I suspect that data model might not be properly normalized (i.e. LEGO should be in its own column).
If that "first word" changes, consider a slight modification in the ORDER BY clause. For example (based on @Saravana's code; thank you for the sample data!):
SQL> with legs(leg) as (
2 select 'LEGO 1' from dual union
3 select 'LEGO 2' from dual union
4 select 'LEGO 3' from dual union
5 select 'LEGO 4' from dual union
6 select 'LEGO 5' from dual union
7 select 'LEGO 6' from dual union
8 select 'LEGO 7' from dual union
9 select 'LEGO 8' from dual union
10 select 'LEGO 9' from dual union
11 select 'TRIAGO 10' from dual union --> here
12 select 'LEGO 11' from dual union
13 select 'LEGO 15' from dual union
14 select 'LEGO 12A' from dual union
15 select 'VIGO 12B' from dual union --> here
16 select 'LEGO 13A' from dual union
17 select 'LEGO 13B' from dual union
18 select 'LEGO 14A' from dual union
19 select 'LEGO 14B' from dual
20 )
21 select leg from legs
22 order by regexp_substr(leg, '^\w+'),
23 to_number(regexp_substr(leg, '\d+')),
24 regexp_substr(leg, '\w+$');
LEG
---------
LEGO 1
LEGO 2
LEGO 3
LEGO 4
LEGO 5
LEGO 6
LEGO 7
LEGO 8
LEGO 9
LEGO 11
LEGO 12A
LEGO 13A
LEGO 13B
LEGO 14A
LEGO 14B
LEGO 15
TRIAGO 10 --> here
VIGO 12B --> here
18 rows selected.
SQL>
Upvotes: 2
Reputation: 55
I have run query with this set of data and it is working fine.
select * from A order by to_number(regexp_substr(regexp_substr(A,'[^ ]+',1,2),'[^A-Z]+',1,1)) Asc;
Upvotes: 0
Reputation: 12817
You need to substring the number and alphabet from the LINENAME
and do sorting
SELECT * FROM WA_GA_TBL_LINES
WHERE LINENAME LIKE 'LEGO%'
AND SECTIONID_FK = 'SC0013'
AND LINENAME != 'LEGO 16'
ORDER BY TO_NUMBER(SUBSTR(LINENAME,5, 3)),SUBSTR(LINENAME,8, 2)
you can control the order based on the alphabet when its null and not null cases
ORDER BY TO_NUMBER(SUBSTR(LINENAME,5, 3)) ASC ,SUBSTR(LINENAME,8, 2) ASC NULLS FIRST
SQL Fiddle
with legs(leg) as (
select 'LEGO 1' from dual union
select 'LEGO 2' from dual union
select 'LEGO 3' from dual union
select 'LEGO 4' from dual union
select 'LEGO 5' from dual union
select 'LEGO 6' from dual union
select 'LEGO 7' from dual union
select 'LEGO 8' from dual union
select 'LEGO 9' from dual union
select 'LEGO 10' from dual union
select 'LEGO 11' from dual union
select 'LEGO 15' from dual union
select 'LEGO 12A' from dual union
select 'LEGO 12B' from dual union
select 'LEGO 13A' from dual union
select 'LEGO 13B' from dual union
select 'LEGO 14A' from dual union
select 'LEGO 14B' from dual
) select leg from legs order by to_number(substr(leg,5, 3)),substr(leg,8, 2)
| LEG |
|----------|
| LEGO 1 |
| LEGO 2 |
| LEGO 3 |
| LEGO 4 |
| LEGO 5 |
| LEGO 6 |
| LEGO 7 |
| LEGO 8 |
| LEGO 9 |
| LEGO 10 |
| LEGO 11 |
| LEGO 12A |
| LEGO 12B |
| LEGO 13A |
| LEGO 13B |
| LEGO 14A |
| LEGO 14B |
| LEGO 15 |
Upvotes: 3
Reputation: 887
The result can be achieved using REGEXP as follows -
SELECT * FROM WA_GA_TBL_LINES
WHERE LINENAME LIKE 'LEGO%'
AND SECTIONID_FK = 'SC0013'
AND LINENAME != 'LEGO 16'
ORDER BY TO_NUMBER(REGEXP_REPLACE(LINENAME,'[^0-9]',''));
Result:
LEGO 1
LEGO 2
LEGO 3
LEGO 4
LEGO 5
LEGO 6
LEGO 7
LEGO 8
LEGO 9
LEGO 10
LEGO 11
LEGO 12A
LEGO 12B
LEGO 13A
LEGO 13B
LEGO 14A
LEGO 14B
LEGO 15
Upvotes: 4