6

我正在使用 SQL Server,列是 a 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

到目前为止,我所拥有的是:

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

但是这条 SQL 语句将 '14 Draft' 放在 '26' 之后。

有人可以帮忙吗?谢谢

4

4 回答 4

3

你的 WHERE 语句是......奇怪的复杂。

看起来您想按整数顺序按任何前导数字排序,然后按余数排序。如果是这样,您应该将其作为单独的子句来执行,而不是尝试将所有内容都放在一个子句中。您遇到的具体问题是您只允许使用一位数,而不是两位或更多。(而且没有两个这样的东西。)

这是您的修复,以及SQLFiddle,使用两个单独的计算列测试您的 ORDER BY。(请注意,这假设 的数字部分asdNumNew适合 a 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
于 2013-05-31T17:41:56.603 回答
0

如果字符串中的所有数字都相当小,比如不超过10 位,您可以将字符串中的所有数字扩展为正好10 位:

123A -> 0000000123A

 S4 -> S0000000004

A3B89 -> A0000000003B0000000089

依此类推,然后对它们进行排序

-- 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)
于 2013-05-31T18:22:08.723 回答
0

试试这个
声明@t表(编号nvarchar(20))插入@t选择'L010'联合全部选择'L011'联合全部选择'L011'联合全部选择'L001'联合全部选择'L012'联合全部选择'18 '
联合全部选择'8'联合全部选择'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 * 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

o/p

**Number**
B004
B006
B008
B018
G001
G002
G011
L001
L010
L011
L011
L012
UG001
UG011
8
17
18
于 2017-02-09T08:41:49.753 回答
0

我有类似的东西,但有可能将破折号作为前导字符和尾随空格。这段代码对我有用。

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
于 2018-01-03T19:10:53.953 回答