Reputation: 15710
Here is my current query..
SELECT invNumber FROM invs ORDER BY invNumber DESC
..and result is:
1032-IN1
1032
1031-IN1
1031
1030-IN4
1030-IN3
1030-IN2
1030-IN1
1030
1029
Expected result is:
1032
1032-IN1
1031
1031-IN1
1030
1030-IN1
1030-IN2
1030-IN3
1030-IN4
1029
How can I achieve this?
Upvotes: 0
Views: 59
Reputation: 13006
Considering different datatypes, this solution will help.
select [invNumber] from invs
order by left([invNumber], (case when charindex([invNumber], '-') > 1 then charindex([invNumber], '-')-1 else len([invNumber]) end)) desc,
right([invNumber], case when charindex([invNumber], '-') > 1 then len([invNumber]) - charindex([invNumber], '-') else
len([invNumber]) end) asc
Upvotes: 0
Reputation: 95561
As i mentioned, it sounds like you need to normalise your data. The reason you're getting the sort order you have is because you're expecting strings to sort in the same order as a numerical data type; where that simply isn't true. A value like '2'
is greater than '10'
with strings.
I would split the values into 3 parts, and CAST
/CONVERT
them before ordering. There is likely a better way here, but it's the way I got to the logic in the end:
SELECT YT.YourColumn
FROM (VALUES('1032-IN1'),
('1032'),
('1031-IN1'),
('1031'),
('1030-IN4'),
('1030-IN3'),
('1030-IN2'),
('1030-IN1'),
('1030'),
('1029'))YT(YourColumn)
CROSS APPLY (VALUES(NULLIF(CHARINDEX('-',YT.YourColumn),0)))CI(h)
CROSS APPLY (VALUES(TRY_CONVERT(int,LEFT(YT.YourColumn,ISNULL(CI.h-1,LEN(YT.YourColumn)))),STUFF(YT.YourColumn,1,CI.h,'')))V(Incremental,RightPart)
CROSS APPLY (VALUES(LEFT(V.RightPart,PATINDEX('%[0-9]%',V.Rightpart)-1),TRY_CONVERT(int,STUFF(V.RightPart,1,PATINDEX('%[0-9]%',V.Rightpart)-1,''))))R([In],InNo)
ORDER BY V.Incremental DESC, R.[In], R.InNo DESC;
Upvotes: 0
Reputation: 521259
We can try a two-tiered sort here:
SELECT invNumber
FROM invs
ORDER BY
CASE WHEN invNumber LIKE '%-%'
THEN CAST(SUBSTRING(invNumber, 1, CHARINDEX('-', invNumber)-1) AS INT)
ELSE CAST(invNumber AS INT) END DESC,
invNumber;
The first level of sorting checks if the invoice number contains a dash component. If it does, then we substring off the number only and cast to integer. Otherwise, if the invoice number be a pure number, we just cast right away. The second level of sorting uses invNumber
directly, to break the tie, should one occur.
Upvotes: 3