erikTsomik
asked on
sql alphanumeric order
I have a table that stores page in alphanumeric manner. I need to be able order the page. The issue is they are in alphanumeric
The sample data is here
sample query is here
The sample data is here
E-1.html
E-10.html
E-11.html
E-12.html
E-13.html
E-14.html
E-15.html
E-16.html
E-17.html
E-18.html
E-19.html
E-2.html
E-20.html
E-21.html
E-22.html
E-23.html
E-24.html
E-25.html
E-26.html
E-27.html
E-28.html
E-29.html
E-3.html
E-30.html
E-31.html
E-32.html
E-33.html
E-34.html
E-35.html
E-36.html
E-37.html
E-38.html
E-39.html
E-3a.html
E-4.html
E-40.html
E-41.html
E-42.html
E-43.html
E-44.html
E-45.html
E-46.html
E-47.html
E-48.html
E-49.html
E-5.html
E-50.html
E-6.html
E-7.html
E-8.html
E-9.html
sample query is here
SELECT *
FROM dbTempType
WHERE name LIKE 'E-%'
ORDER BY
CASE
WHEN ISNUMERIC(name)=1
THEN CAST(name as int)
WHEN PATINDEX('%[^0-9]%',name) > 1
THEN CAST(
LEFT(
name,
PATINDEX('%[^0-9]%',name) - 1
) as int)
ELSE 2147483648
END,
CASE
WHEN ISNUMERIC(name)=1
THEN NULL
WHEN PATINDEX('%[^0-9]%',name) > 1
THEN SUBSTRING(
name,
PATINDEX('%[^0-9]%',name) ,
50
)
ELSE name
END
select filename from dbTempType
order by left(filename, 2), parse (substring(filename, patindex('%[0-9]%', filename), patindex('%[^0-9]%', substring(filename, 1+patindex('%[0-9]%',filen ame), 999))) as int)
order by left(filename, 2), parse (substring(filename, patindex('%[0-9]%', filename), patindex('%[^0-9]%', substring(filename, 1+patindex('%[0-9]%',filen
select name, left(name, patindex('%[0-9]%', name)-1),
substring(name, patindex('%[0-9]%', name), patindex('%[^0-9]%', substring(name, 1+patindex('%[0-9]%',name) , 999))) ,
substring(name, 1+len(substring(reverse(na me), patindex('%[0-9]%',reverse (name)), 999)), 999)
from dbtemptype
order by left(name, 2),
parse (substring(name, patindex('%[0-9]%', name), patindex('%[^0-9]%', substring(name, 1+patindex('%[0-9]%',name) , 999))) as int),
substring(name, 1+len(substring(reverse(na me), patindex('%[0-9]%',reverse (name)), 999)), 999)
substring(name, patindex('%[0-9]%', name), patindex('%[^0-9]%', substring(name, 1+patindex('%[0-9]%',name)
substring(name, 1+len(substring(reverse(na
from dbtemptype
order by left(name, 2),
parse (substring(name, patindex('%[0-9]%', name), patindex('%[^0-9]%', substring(name, 1+patindex('%[0-9]%',name)
substring(name, 1+len(substring(reverse(na
ASKER
I am getting the parse is not recognized built-in function name
that's strange. Parse is valid tsql: https://msdn.microsoft.com/en-us/library/hh213316.aspx
try replacing it with the word cast.
try replacing it with the word cast.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
if your data is exact format use below query
select convert(int,replace(replac e (column,'E-',''),'.html',' ')) from Table name
select convert(int,replace(replac
CONVERT() or CAST() can cause failure is the data isn't suitable.
It would be better in my view to use TRY_CONVERT() or TRY_CAST() that are only available in recent versions of SQL Server and at least those will not fail if the data cannot be converted. However they return NULL if they cannot convert which would affect the sorting.
The reason I proposed using concatenation like this:
right('0000000000' + replace(replace([name],'E- ',''),'.ht ml',''),10 )
is because it avoids conversion failures
It would be better in my view to use TRY_CONVERT() or TRY_CAST() that are only available in recent versions of SQL Server and at least those will not fail if the data cannot be converted. However they return NULL if they cannot convert which would affect the sorting.
The reason I proposed using concatenation like this:
right('0000000000' + replace(replace([name],'E-
is because it avoids conversion failures
I propose breaking it into parts and sorting on the parts. Otherwise I don't think you'll end up with the sort order you want. I added the bolded data to point out potential sort issues later.
I used CROSS APPLYs to assign alias names to avoid repeating computations and to make the code easier to follow (at least to me).
SELECT page --*
FROM (VALUES
('E-1.html'),('E-10.html') ,('E-11.ht ml'),('E-1 2.html'),( 'E-13.html '),
('E-14.html'),('E-15.html' ),('E-16.h tml'),('E- 17.html'), ('E-18.htm l'),
('E-19.html'),('E-2.html') ,('E-20.ht ml'),('E-2 1.html'),( 'E-22.html '),
('E-23.html'),('E-24.html' ),('E-25.h tml'),('E- 26.html'), ('E-27.htm l'),
('E-28.html'),('E-29.html' ),('E-3.ht ml'),('E-3 0.html'),( 'E-31.html '),
('E-32.html'),('E-33.html' ),('E-34.h tml'),('E- 35.html'), ('E-36.htm l'),
('E-37.html'),('E-38.html' ),('E-39.h tml'),('E- 3a.html'), ('E-4.html '),
('E-40.html'),('E-41.html' ),('E-42.h tml'),('E- 43.html'), ('E-44.htm l'),
('E-45.html'),('E-46.html' ),('E-47.h tml'),('E- 48.html'), ('E-49.htm l'),
('E-5.html'),('E-50.html') ,('E-6.htm l'),('E-7. html'),('E -8.html'),
('E-9.html'),
('E-3ac.html'),('E-3z.html '),
('E-3') /*I deliberately removed the "." from the data to demonstrate how it sorts without it */
) pages(page)
CROSS APPLY (
SELECT CHARINDEX('.', REVERSE(page)) AS suffix_length
) AS ca1
CROSS APPLY (
SELECT LEFT(page, LEN(page) - suffix_length) AS page_without_suffix
) AS ca2
CROSS APPLY (
SELECT PATINDEX('%[0-9]%', page_without_suffix) AS first_digit,
LEN(page_without_suffix) - PATINDEX('%[0-9]%', REVERSE(page_without_suffi x)) + 1 AS last_digit
) AS ca3
ORDER BY
CASE WHEN first_digit = 0 THEN page_without_suffix
ELSE LEFT(page_without_suffix, first_digit - 1) END,
CASE WHEN first_digit = 0 THEN 0
ELSE CAST(SUBSTRING(page_withou t_suffix, first_digit, last_digit - first_digit + 1) AS int) END,
CASE WHEN first_digit = 0 THEN ''
ELSE SUBSTRING(page_without_suf fix, last_digit + 1, 8000) END,
RIGHT(page, suffix_length)
I used CROSS APPLYs to assign alias names to avoid repeating computations and to make the code easier to follow (at least to me).
SELECT page --*
FROM (VALUES
('E-1.html'),('E-10.html')
('E-14.html'),('E-15.html'
('E-19.html'),('E-2.html')
('E-23.html'),('E-24.html'
('E-28.html'),('E-29.html'
('E-32.html'),('E-33.html'
('E-37.html'),('E-38.html'
('E-40.html'),('E-41.html'
('E-45.html'),('E-46.html'
('E-5.html'),('E-50.html')
('E-9.html'),
('E-3ac.html'),('E-3z.html
('E-3') /*I deliberately removed the "." from the data to demonstrate how it sorts without it */
) pages(page)
CROSS APPLY (
SELECT CHARINDEX('.', REVERSE(page)) AS suffix_length
) AS ca1
CROSS APPLY (
SELECT LEFT(page, LEN(page) - suffix_length) AS page_without_suffix
) AS ca2
CROSS APPLY (
SELECT PATINDEX('%[0-9]%', page_without_suffix) AS first_digit,
LEN(page_without_suffix) - PATINDEX('%[0-9]%', REVERSE(page_without_suffi
) AS ca3
ORDER BY
CASE WHEN first_digit = 0 THEN page_without_suffix
ELSE LEFT(page_without_suffix, first_digit - 1) END,
CASE WHEN first_digit = 0 THEN 0
ELSE CAST(SUBSTRING(page_withou
CASE WHEN first_digit = 0 THEN ''
ELSE SUBSTRING(page_without_suf
RIGHT(page, suffix_length)
ASKER
Open in new window
The data is here
Open in new window