如何在sql server中自定义排序数据

时间:2014-04-15 07:16:49

标签: sql sql-server tsql

我使用的是Sql server 2008 r2,我需要按以下数据订购:

CardNo

R-1  
R-2
R-12
R-1A
R-3
R-2B

结果应如下所示

CardNo

R-1  
R-1A
R-2
R-2B
R-3
R-12

我在order by子句中尝试过不同的组合,但没有用过:

select * from [Coll2012-13] where  
    SUBSTRING(CardNo, 1, 1) IN ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'W', 'X', 'Y', 'Z') 
    AND SUBSTRING(CardNo, 2, 1) IN ('-') 
    AND SUBSTRING(CardNo, 3, 1) IN ('1', '2', '3', '4', '5', '6', '7', '8', '9', '0')
    and Landmark='Anandbagh' order by LEN(CardNo),CardNo ASC

5 个答案:

答案 0 :(得分:1)

假设:值始终采用格式'字母 - 字母数字字符串'

试试这个:

select card_no
from [Coll2012-13]
order by left(card_no,1),
case
when isnumeric(substring(card_no,3, len(card_no))) = 1
then cast(substring(card_no,3, len(card_no)) as int)
else cast(substring(card_no,3, patindex('%[A-Z]%',substring(card_no,3, len(card_no)))-1) as int)
end,
case 
when patindex('%[A-Z]%', substring(card_no,3,len(card_no))) > 0
then substring(card_no,patindex('%[A-Z]%', substring(card_no,3,len(card_no)))+2,1)
end

这是如何工作的:首先检查起始字母。接下来,检查字母数字部分实际上是否只是数字。如果是,请获取该部分的整数值。如果不是,请获取它的数字部分并将其用作排序值。最后,如果字母数字部分确实包含一个字母,请将其用作另一个排序值。

演示here

答案 1 :(得分:0)

试试这个

with cte
AS
(
    select 
       * 
       ,substring(CardNo, 1, charindex('-')-1) RealRank1
       ,substring(CardNo, charindex('-')+ 1, 10) RealRank2
    from 
       [Coll2012-13] 
)
select 
    *
from 
    cte
order by
    RealRank1
    ,RealRank2

答案 2 :(得分:0)

一个简单的 - 但应该保持' - 解决方案是创建一个排序表并将该表连接到结果集。该表包含所有CardNo值并将排序顺序与它们相关联。

编辑:

CREATE TABLE CardNoOrderHelper (
    CardNo VARCHAR(16)
    , OrderRank INT CONSTRAINT DF_CardNoOrderHelper_OrderRank DEFAULT 0
    , PRIMARY KEY CLUSTERED (
        CardNo ASC
    )
);

-- Fill your table with the expected sort order (dinstinct insert, than adjust the order ranks)

SELECT
    *
FROM
    [Coll2012-13] AS T
    LEFT JOIN CardNoOrderHelper CH
        ON T.CardNo = CH.CardNo
ORDER BY
    T.OrderRank

正如我所说,你必须保持这张桌子。当结果集很小时,可以手动完成。

答案 3 :(得分:0)

您应该用“”替换所有非数字字符,并将其余部分转换为数字。然后按数字排序。

您可以尝试使用此处所述的功能SQL Server 2000: how do I return only the number from a phone number column 为此

答案 4 :(得分:0)

我有类似的问题。我在下面使用过这个查询。

要使用此查询,您必须知道ID(字符串)的最大长度,并且我已调整此查询中的格式以使用Mark-Number + Alphabet(示例R-1,R-1A,R-11,R-11A ,R-1AA,R-1B)

查询:

select 
 b.CardNo, b.separatorIndex
 ,b.Mark, b.Mark_length
 ,case b.isNumericMark1 + b.isNumericMark2 + b.isNumericMark3
   when 1 then cast (b.Mark1 as int)
   when 2 then cast (b.Mark1 + b.Mark2 as int) 
   when 3 then cast (b.Mark1 + b.Mark2 + b.Mark3 as int) 

  end as Mark1
from
(
    select 
        a.CardNo
        ,charindex('-',a.cardNo,0) as separatorIndex
        , len(a.cardNo) - charindex('-',a.cardNo,0) as Mark_length
        , substring(a.CardNo,0,charindex('-',a.cardNo,0)) as Mark

        , substring(a.CardNo,charIndex('-',a.cardNo,0)+1,1) as Mark1
        , isnumeric(substring(a.CardNo,charIndex('-',a.cardNo,0)+1,1*1)) as isNumericMark1

        , substring(a.CardNo,charIndex('-',a.cardNo,0)+2,1) as Mark2
        , isnumeric(substring(a.CardNo,charIndex('-',a.cardNo,0)+2,1)) as isNumericMark2

        , substring(a.CardNo,charIndex('-',a.cardNo,0)+3,1) as Mark3
        , isnumeric(substring(a.CardNo,charIndex('-',a.cardNo,0)+3,1)) as isNumericMark3

    from [Coll2012-13] a
) b
order by Mark,Mark1,Mark_length

结果:

CardNo               separatorIndex Mark                 Mark_length Mark1
-------------------- -------------- -------------------- ----------- -----------
R-1                  2              R                    1           1
R-1A                 2              R                    2           1
R-2                  2              R                    1           2
R-2B                 2              R                    2           2
R-3                  2              R                    1           3
R-12                 2              R                    2           12

希望得到这个帮助。