分割后SQL排序数字字符串

时间:2017-08-17 16:54:55

标签: sql sql-server-2008

我目前在表格列中有char值,其格式为" IS - "然后是1到5个数字,一个可能的句号,带有2个数字或句点后面的字母。

  

例如,IS-1,IS-12,IS-123,IS-123.11,IS-123.a。

我需要拆分字符串,以便我只抓取数字部分,对字符串ASC进行排序,然后按照它们的方式将字符串重新组合在一起。

解释。我有以下一组值,IS-1170, IS-1171, IS-1172, IS-1173, IS-1174, IS-870.a, IS-871.a, IS-872.a.正如您所看到的,因为IS-1出现在IS-8之前,它们是按数字顺序排序的。

知道从哪里开始?我在考虑使用CASE,但我不确定如何继续。

感谢。

3 个答案:

答案 0 :(得分:2)

ORDER BY中执行字符串功能以仅删除该号码。这样的事情应该有效:

SELECT col
FROM table
ORDER BY CAST(CASE WHEN ISNUMERIC(SUBSTRING(col,4,20)) = 1
              THEN SUBSTRING(col,4,20)
              ELSE LEFT(SUBSTRING(col,4,20),CHARINDEX('.',SUBSTRING(col,4,20),0)-1)
         END AS NUMERIC)

这将首先删除IS-并检查字符串的其余部分是否为数字。如果是,它将保留小数位,否则将删除.和以下字母字符。

这假设您在数字小数位的情况下的预期排序是:

IS-123.A
IS-123.1
IS-123.2

如果您不关心十进制/句点之后的内容,那么只需:

ORDER BY CAST(LEFT(SUBSTRING(col,4,20),CHARINDEX('.',SUBSTRING(col,4,20),0)-1) AS NUMERIC)

答案 1 :(得分:0)

如果我理解正确,这可能会对您有所帮助:

DECLARE @mockup TABLE(ID INT IDENTITY,YourExample VARCHAR(100));
INSERT INTO @mockup VALUES
 ('IS-1, IS-12, IS-123, IS-123.11, IS-123.a.')
,('IS-1170, IS-1171, IS-1172, IS-1173, IS-1174, IS-870.a, IS-871.a, IS-872.a');

WITH Splitted AS
(
    SELECT *
          ,CAST('<x>' + REPLACE(m.YourExample,',','</x><x>') + '</x>' AS XML) AS SplitAtComma
    FROM @mockup AS m
)
,NumberExtracted AS
(
    SELECT s.ID
          ,part.value('text()[1]','nvarchar(max)') AS OnePart
          ,CAST('<y>' + REPLACE(REPLACE(part.value('text()[1]','nvarchar(max)'),'.','-'),'-','</y><y>') + '</y>' AS XML).value('/y[2]/text()[1]','int') AS TheNumber 
    FROM Splitted AS s
    CROSS APPLY s.SplitAtComma.nodes('/x') AS A(part)
)
SELECT *
FROM NumberExtracted
ORDER BY ID,TheNumber;

第一个CTE使用字符串拆分通过XML获取原始字符串中的所有值(顺便说一句:从不存储以逗号分隔的值!)。 第二个CTE将使用相同的方法提取数字,类型安全为INT。 您最终可以在ORDER BY中使用它。

结果:

+----+-----------+-----------+
| ID | OnePart   | TheNumber |
+----+-----------+-----------+
| 1  | IS-1      | 1         |
+----+-----------+-----------+
| 1  | IS-12     | 12        |
+----+-----------+-----------+
| 1  | IS-123    | 123       |
+----+-----------+-----------+
| 1  | IS-123.11 | 123       |
+----+-----------+-----------+
| 1  | IS-123.a. | 123       |
+----+-----------+-----------+
| 2  | IS-870.a  | 870       |
+----+-----------+-----------+
| 2  | IS-871.a  | 871       |
+----+-----------+-----------+
| 2  | IS-872.a  | 872       |
+----+-----------+-----------+
| 2  | IS-1170   | 1170      |
+----+-----------+-----------+
| 2  | IS-1171   | 1171      |
+----+-----------+-----------+
| 2  | IS-1172   | 1172      |
+----+-----------+-----------+
| 2  | IS-1173   | 1173      |
+----+-----------+-----------+
| 2  | IS-1174   | 1174      |
+----+-----------+-----------+

答案 2 :(得分:0)

IF OBJECT_ID(N'tempdb..##table1', N'U') IS NOT NULL   
DROP TABLE ##table1;  
create table ##table1(col1 varchar(20))

declare @query as nvarchar(max)
declare @var1 as varchar(max)='IS-1, IS-12, IS-123, IS-123.11, IS-123.a.,IS-1170, IS-1171, IS-1172, IS-1173, IS-1174, IS-870.a, IS-871.a, IS-872.a.'
set @var1=replace(@var1,',','''),(''')
set @var1='('''+@var1+''')'
set @var1=replace(@var1,' ','')
set @query='insert into ##table1 values'+@var1
EXEC sp_executesql @query
IF OBJECT_ID(N'tempdb..##table2', N'U') IS NOT NULL   
DROP TABLE ##table2;  
select * into ##table2  from ##table1 order by cast(replace(replace(replace(col1,'IS-',''),'.a.',''),'.a','') as float)

declare @results varchar(max)
select @results = coalesce(@results + ', ', '') +  convert(varchar(12),col1) from ##table2
select @results

DROP TABLE ##table1 
DROP TABLE ##table2