[英]Sorting VARCHAR column with alphanumeric entries
I am using SQL Server, the column is a VARCHAR(50)
and I want to sort it like this:我正在使用 SQL Server,该列是VARCHAR(50)
,我想像这样对其进行排序:
1A
1B
2
2
3
4A
4B
4C
5A
5B
5C
5N
14 Draft
21
22A
22B
23A
23B
23C
23D
23E
25
26
FR01584
MISC
What I have so far is:到目前为止,我所拥有的是:
Select *
From viewASD
ORDER BY
Case When IsNumeric(LEFT(asdNumNew,1)) = 1
Then CASE When IsNumeric(asdNumNew) = 1
Then Right(Replicate('0',20) + asdNumNew + '0', 20)
Else Right(Replicate('0',20) + asdNumNew, 20)
END
When IsNumeric(LEFT(asdNumNew,1)) = 0
Then Left(asdNumNew + Replicate('',21), 20)
End
But this SQL statement puts '14 Draft' right after '26'.但是这条 SQL 语句将 '14 Draft' 放在 '26' 之后。
Could someone help?有人可以帮忙吗? Thanks谢谢
Your WHERE statement is... oddly complex.你的 WHERE 语句是......奇怪的复杂。
It looks like you want to sort by any leading numeric digits in integer order, and then sort by the remainder.看起来您想按整数顺序按任何前导数字排序,然后按余数排序。 If so, you should do that as separate clauses, rather than trying to do it all in one.如果是这样,您应该将其作为单独的子句来执行,而不是尝试将所有内容都放在一个子句中。 The specific issue you're having is that you're only allowing for a single-digit number, instead of two or more.您遇到的具体问题是您只允许使用一位数,而不是两位或更多。 (And there's No such thing as two .) (而且没有两个这样的东西。)
Here's your fix, along with a SQLFiddle , using two separate calculated columns tests for your ORDER BY.这是您的修复,以及SQLFiddle ,使用两个单独的计算列测试您的 ORDER BY。 (Note that this assumes the numeric portion of asdNumNew
will fit in a T-SQL int
. If not, you'll need to adjust the CAST and the maximum value on the first ELSE.) (请注意,这假设asdNumNew
的数字部分适合T-SQL int
。如果不适合,则需要调整 CAST 和第一个 ELSE 的最大值。)
SELECT * FROM viewASD
ORDER BY
CASE
WHEN ISNUMERIC(asdNumNew)=1
THEN CAST(asdNumNew as int)
WHEN PATINDEX('%[^0-9]%',asdNumNew) > 1
THEN CAST(
LEFT(
asdNumNew,
PATINDEX('%[^0-9]%',asdNumNew) - 1
) as int)
ELSE 2147483648
END,
CASE
WHEN ISNUMERIC(asdNumNew)=1
THEN NULL
WHEN PATINDEX('%[^0-9]%',asdNumNew) > 1
THEN SUBSTRING(
asdNumNew,
PATINDEX('%[^0-9]%',asdNumNew) ,
50
)
ELSE asdNumNew
END
If all numbers within the string are reasonably small, say not exceeding 10 digits, you may expand all the numbers in the string to be exactly 10 digits:如果字符串中的所有数字都相当小,比如不超过10 位,您可以将字符串中的所有数字扩展为正好10 位:
123A -> 0000000123A 123A -> 0000000123A
S4 -> S0000000004
A3B89 -> A0000000003B0000000089 A3B89 -> A0000000003B0000000089
and so on and then sort them依此类推,然后对它们进行排序
-- Expand all numbers within S by zeros to be MaxLen
create function [dbo].ExpandNumbers(@S VarChar(4000), @maxlen integer) returns VarChar(4000)
as
begin
declare @result VarChar(4000);
declare @buffer VarChar(4000);
declare @Ch Char;
declare @i integer;
set @buffer = '';
set @result = '';
set @i = 1;
while (@i <= len(@S))
begin
set @Ch = substring(@S, @i, 1);
if ((@Ch >= '0') and (@Ch <= '9'))
set @buffer = @buffer + @Ch
else
begin
if (len(@buffer) > 0)
set @result = @result + right(replicate('0', @maxlen) + @buffer, @maxlen);
set @buffer = '';
set @result = @result + @Ch;
end;
set @i = @i + 1;
end;
if (len(@buffer) > 0)
set @result = @result + right(replicate('0', @maxlen) + @buffer, @maxlen);
return @result;
end;
-- Final query is
select *
from viewASD
order by [dbo].ExpandNumbers(asdNumNew)
TRY THIS尝试这个
DECLARE @t table (Number nvarchar(20))
INSERT INTO @t
SELECT 'L010'
UNION ALL SELECT 'L011'
UNION ALL SELECT 'L011'
UNION ALL SELECT 'L001'
UNION ALL SELECT 'L012'
UNION ALL SELECT '18'
UNION ALL SELECT '8'
UNION ALL SELECT '17'
UNION ALL SELECT 'B004'
UNION ALL SELECT 'B006'
UNION ALL SELECT 'B008'
UNION ALL SELECT 'B018'
UNION ALL SELECT 'UG001'
UNION ALL SELECT 'UG011'
UNION ALL SELECT 'G001'
UNION ALL SELECT 'G002'
UNION ALL SELECT 'G011';
SELECT Number
FROM @t
ORDER BY
CAST
(
SUBSTRING
(
Number
, 1
, CASE
WHEN patindex('%[^0-9]%',Number) > 0 THEN patindex('%[^0-9]%',Number) - 1
ELSE LEN(Number) END
) AS int
)
, Number
I had something similar, but with the possibility of dashes as leading characters as well as trailing spaces.我有类似的东西,但有可能将破折号作为前导字符和尾随空格。 This code worked for me.这段代码对我有用。
SELECT
my_column,
PATINDEX('%[^0-9]%',my_column) AS first_alpha_position,
CONVERT(INT,
CASE
WHEN PATINDEX('%[^0-9]%',my_column) = 0 OR PATINDEX('-%',my_column) = 1
THEN ABS(my_column)
ELSE SUBSTRING(my_column,1,PATINDEX('%[^0-9]%',my_column) -1)
END) AS numeric_value,
LTRIM(
SUBSTRING(my_column,PATINDEX('%[^0-9]%',my_column),LEN(my_column)-PATINDEX('%[^0-9]%',my_column)+1)
) AS alpha_chars
FROM my_table
ORDER BY numeric_value,alpha_chars
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.