Is there a collation to sort the following strings in the following order 1,2,3,6,10,10A,10B,11?
No. Collation is about alphabetical sorting, depending on code page, accent, case, width, kana. Numbers characters (0-9) have none of there properties.
So 9
is always after 10B
in any sort.
You have to split it up as you noted or sort like this:
ORDER BY
RIGHT(' ' + MyColumn, 30)
The length in the right determines how many spaces you have.
You could of course:
- have 2 columns to make this unnecessary (and far quicker) and have a computed column to combine them
- insist on leading zeros
right justify in a char (a stored version of my RIGHT above)
The latter 2 suggestions are like my RIGHT above and slightly different. Quicker to sort (no processing of the colukmn needed) but more storage required
I would setup a computed column then sort based on that. Something like
CAST(
CASE WHEN IS_NUMERIC(left(OtherColumn, 2) = 1) then
left(OtherColumn,2)
else
left(otherColumn, 1)
AS INT)
Then use this column to sort by as you can now index the column.
If you want a painful way to prove what @gbn is saying (essentially that you can't tell a collation to order substrings differently), you can make a quick #temp table that has a coefficient for the order you expect, and see if ordering by any collation returns the same order:
CREATE TABLE #foo(id INT, n NVARCHAR(10));
CREATE TABLE #bar(collation SYSNAME);
SET NOCOUNT ON;
INSERT #foo SELECT 1,'1'
UNION SELECT 2,'2'
UNION SELECT 3,'3'
UNION SELECT 4,'6'
UNION SELECT 5,'10'
UNION SELECT 6,'10A'
UNION SELECT 7,'10B'
UNION SELECT 8,'11';
DECLARE @sql NVARCHAR(MAX) = N'';
SELECT @sql += N'
WITH x AS
(
SELECT n, rn = ROW_NUMBER() OVER
(ORDER BY n COLLATE ' + name + ') FROM #foo
)
INSERT #bar
SELECT TOP (1) ''' + name + ''' FROM x
WHERE NOT EXISTS
(
SELECT COUNT(*) FROM #foo AS f
WHERE f.id = x.rn
AND f.n <> x.n
);' FROM sys.fn_helpcollations();
EXEC sp_executesql @sql;
SELECT collation FROM #bar;
GO
DROP TABLE #foo, #bar;
This runs for me in about 10 seconds and yields 0 rows - meaning no collation available to SQL Server (at least 2008 R2, haven't tried Denali) will sort in the way you expect. You need a different way to define sorting.