如何按 multipart X.Y[.Z] "version" 数字对查询结果进行排序?
How to order query result by multipart X.Y[.Z] "version" numbers?
我有这个数据:
nov_id
2.1.1
2.1.10
2.1.11
2.1.12
2.1.13
2.1.14
2.1.2
2.1.3
2.1.4
2.1.5
2.1.6
2.1.7
2.1.8
2.1.9
2.2
2.3
2.4
2.5
2.6
我需要订购我的结果,所以我的预期结果是这样的:
nov_id
2.1.1
2.1.2
2.1.3
2.1.4
2.1.5
2.1.6
2.1.7
2.1.8
2.1.9
2.1.10
2.1.11
2.1.12
2.1.13
2.1.14
2.2
2.3
2.4
2.5
2.6
这是我的尝试之一:
Select nov_id
From dbo.NS_tbl_sc_novedad
Order by Convert(int,Left(Ltrim(Rtrim(replace(nov_id,'.','')))+'0000',4));
我试图粘贴一些零并以此为序,但显然我还没有明白。
对于您的特定数据,这将有效:
order by left(mov_id, 3),
len(mov_id),
mov_id
我们的想法是按长度排序,因为末尾较小的数字长度较短 -- 给定值的存储方式。
这可以修改为更通用,具体取决于您的数据的实际情况。
这是我的(可能设计过度的解决方案)...但它有效
declare @temp table (value varchar(20),orderby int)
insert into @temp (value)
Values( '2.1.1'),
('2.1.10'),
('2.1.11'),
('2.1.12'),
('2.1.13'),
('2.1.14'),
('2.1.2'),
('2.1.3'),
('2.1.4'),
('2.1.5'),
('2.1.6'),
('2.1.7'),
('2.1.8'),
('2.1.9'),
('2.2'),
('2.3'),
('2.4'),
('2.5'),
('2.6')
UPdate @temp set orderby= case when len(replace(value,'.',''))=2 then replace(value,'.','')*100
when len(replace(value,'.',''))=3 then replace(value,'.','')*10
else replace(value,'.','') end
SELECT value FROM @temp
order by orderby ASC
以上给出了结果集
2.1.1
2.1.10
2.1.11
2.1.12
2.1.13
2.1.14
2.1.2
2.1.3
2.1.4
2.1.5
2.1.6
2.1.7
2.1.8
2.1.9
2.2
2.3
2.4
2.5
2.6
这应该适用于任何包含 2 或 3 个部分且数字中包含任意数字的字符串,例如 1546.345.245 和 999.34
select
nov_id
from data
cross apply (
select charindex('.', nov_id) as pos
) as c1
cross apply (
select charindex('.', nov_id, c1.pos+1) as pos
) as c2
order by
convert(int, left(nov_id, c1.pos-1)),
convert(int, substring(nov_id, c1.pos+1, isnull(nullif(c2.pos, 0), 100)-c1.pos-1)),
convert(int, case c2.pos when 0 then 0 else substring(nov_id, c2.pos+1, 100) end)
不过看起来有点乱:)
怎么样:
SELECT nov_id
FROM @example
ORDER BY
CASE WHEN PARSENAME(nov_id, 3) IS NULL THEN
CAST(PARSENAME(nov_id, 2) AS INTEGER)*10000
+CAST(PARSENAME(nov_id, 1) AS INTEGER)*100
ELSE
CAST(PARSENAME(nov_id, 3) AS INTEGER)*10000
+CAST(PARSENAME(nov_id, 2) AS INTEGER)*100
+CAST(PARSENAME(nov_id, 1) AS INTEGER)
END
借鉴 Nathan Bedford 的 'hijacking' How do I split a string so I can access item x?
中的 PARSENAME 函数
它适用于 99.99.99 以内的号码。要支持更多数字,您需要增加 CASE 语句中的倍数。
我有这个数据:
nov_id
2.1.1
2.1.10
2.1.11
2.1.12
2.1.13
2.1.14
2.1.2
2.1.3
2.1.4
2.1.5
2.1.6
2.1.7
2.1.8
2.1.9
2.2
2.3
2.4
2.5
2.6
我需要订购我的结果,所以我的预期结果是这样的:
nov_id
2.1.1
2.1.2
2.1.3
2.1.4
2.1.5
2.1.6
2.1.7
2.1.8
2.1.9
2.1.10
2.1.11
2.1.12
2.1.13
2.1.14
2.2
2.3
2.4
2.5
2.6
这是我的尝试之一:
Select nov_id
From dbo.NS_tbl_sc_novedad
Order by Convert(int,Left(Ltrim(Rtrim(replace(nov_id,'.','')))+'0000',4));
我试图粘贴一些零并以此为序,但显然我还没有明白。
对于您的特定数据,这将有效:
order by left(mov_id, 3),
len(mov_id),
mov_id
我们的想法是按长度排序,因为末尾较小的数字长度较短 -- 给定值的存储方式。
这可以修改为更通用,具体取决于您的数据的实际情况。
这是我的(可能设计过度的解决方案)...但它有效
declare @temp table (value varchar(20),orderby int)
insert into @temp (value)
Values( '2.1.1'),
('2.1.10'),
('2.1.11'),
('2.1.12'),
('2.1.13'),
('2.1.14'),
('2.1.2'),
('2.1.3'),
('2.1.4'),
('2.1.5'),
('2.1.6'),
('2.1.7'),
('2.1.8'),
('2.1.9'),
('2.2'),
('2.3'),
('2.4'),
('2.5'),
('2.6')
UPdate @temp set orderby= case when len(replace(value,'.',''))=2 then replace(value,'.','')*100
when len(replace(value,'.',''))=3 then replace(value,'.','')*10
else replace(value,'.','') end
SELECT value FROM @temp
order by orderby ASC
以上给出了结果集
2.1.1
2.1.10
2.1.11
2.1.12
2.1.13
2.1.14
2.1.2
2.1.3
2.1.4
2.1.5
2.1.6
2.1.7
2.1.8
2.1.9
2.2
2.3
2.4
2.5
2.6
这应该适用于任何包含 2 或 3 个部分且数字中包含任意数字的字符串,例如 1546.345.245 和 999.34
select
nov_id
from data
cross apply (
select charindex('.', nov_id) as pos
) as c1
cross apply (
select charindex('.', nov_id, c1.pos+1) as pos
) as c2
order by
convert(int, left(nov_id, c1.pos-1)),
convert(int, substring(nov_id, c1.pos+1, isnull(nullif(c2.pos, 0), 100)-c1.pos-1)),
convert(int, case c2.pos when 0 then 0 else substring(nov_id, c2.pos+1, 100) end)
不过看起来有点乱:)
怎么样:
SELECT nov_id
FROM @example
ORDER BY
CASE WHEN PARSENAME(nov_id, 3) IS NULL THEN
CAST(PARSENAME(nov_id, 2) AS INTEGER)*10000
+CAST(PARSENAME(nov_id, 1) AS INTEGER)*100
ELSE
CAST(PARSENAME(nov_id, 3) AS INTEGER)*10000
+CAST(PARSENAME(nov_id, 2) AS INTEGER)*100
+CAST(PARSENAME(nov_id, 1) AS INTEGER)
END
借鉴 Nathan Bedford 的 'hijacking' How do I split a string so I can access item x?
中的 PARSENAME 函数它适用于 99.99.99 以内的号码。要支持更多数字,您需要增加 CASE 语句中的倍数。