Sql server 当子id包含“.”时,sql server中的HIRACHICAL排序

Sql server 当子id包含“.”时,sql server中的HIRACHICAL排序,sql-server,sql-server-2008,sql-server-2005,Sql Server,Sql Server 2008,Sql Server 2005,我下面有一些孩子 childid ------------ 1.1 1.2 2.8 2.7 6.5 6.5.1 6.5.15 7.1 8 declare @str nvarchar(max)='1.23.2'; set @str=(select replace(@str,'.','')) select @str 排序顺序将是 childid -------- 1.1 1.2 2.7 2.8 6.5 6.51 6.5.15 7.1 我试着像下面那样转换成英蒂格 childid ----

我下面有一些孩子

childid
------------

1.1
1.2
2.8
2.7
6.5
6.5.1
6.5.15
7.1
8
declare @str nvarchar(max)='1.23.2';

set @str=(select replace(@str,'.',''))
select @str
排序顺序将是

childid 
--------
1.1
1.2
2.7
2.8
6.5
6.51
6.5.15
7.1
我试着像下面那样转换成英蒂格

childid
------------

1.1
1.2
2.8
2.7
6.5
6.5.1
6.5.15
7.1
8
declare @str nvarchar(max)='1.23.2';

set @str=(select replace(@str,'.',''))
select @str
但当

7.1
8
来 它给人一种秩序感

8
7.1 
但我需要像下面这样的订单

7.1
8
如果数字像

7.1.1
7.1.8
6.7.7.7
那么订单应该是

6.7.7.7
7.1.1
7.1.8

我希望有人能帮我解决这个问题

这不是一个优雅的解决方案,但它对我很有用:

DECLARE @t TABLE ( childid VARCHAR(100) )
INSERT  INTO @t
VALUES  ( '1.1' ),
        ( '1.2' ),
        ( '2.8' ),
        ( '2.7' ),
        ( '6.5' ),
        ( '6.5.1' ),
        ( '6.5.15' ),
        ( '7.1' ),
        ( '8' )

;WITH cte AS(SELECT childid + '.' AS childid FROM @t)
SELECT LEFT(childid, LEN(childid) - 1) AS childid
FROM cte
CROSS APPLY(SELECT CHARINDEX('.', childid) i1) c1
CROSS APPLY(SELECT CASE WHEN i1 = 0 THEN 0 ELSE CHARINDEX('.', childid, i1 + 1) END i2) c2
CROSS APPLY(SELECT CASE WHEN i2 = 0 THEN 0 ELSE CHARINDEX('.', childid, i2 + 1) END i3) c3
CROSS APPLY(SELECT CASE WHEN i3 = 0 THEN 0 ELSE CHARINDEX('.', childid, i3 + 1) END i4) c4
CROSS APPLY(SELECT CASE WHEN i4 = 0 THEN 0 ELSE CHARINDEX('.', childid, i4 + 1) END i5) c5
ORDER BY
        CASE WHEN i1 = 0 THEN childid ELSE SUBSTRING(childid, 1, i1 - 1) END,
        CASE WHEN i2 = 0 THEN '0' ELSE SUBSTRING(childid, i1 + 1, i2 - i1 - 1) END,
        CASE WHEN i3 = 0 THEN '0' ELSE SUBSTRING(childid, i2 + 1, i3 - i2 - 1) END,
        CASE WHEN i4 = 0 THEN '0' ELSE SUBSTRING(childid, i3 + 1, i4 - i3 - 1) END,
        CASE WHEN i5 = 0 THEN '0' ELSE SUBSTRING(childid, i4 + 1, i5 - i4 - 1) END
每个交叉应用用于获取点之间的下一个值。 这种方法的缺点是它不是动态的,您应该添加尽可能多的交叉应用,因为可能存在嵌套级别。

尝试如下:

编辑:我也改变了处理像“123abc”这样的非数值的方法

declare @ids table(idList varchar(100))
insert into @ids values
 ('1.1')
,('1.2')
,('2.8')
,('2.7')
,('6.5')
,('6.5.1')
,('6.5.15')
,('7.1')
,('8');

select idList,padded.OrderBy
from @ids as ids
cross apply(select cast('<r>' + replace(idList,'.','</r><r>') + '</r>' as xml)) as AsXml(val)
cross apply
(
    select right('                ' + rtrim(x.y.value('.','varchar(max)')),10) 
    from AsXml.val.nodes('/r') as x(y)
    for xml path('')
) as padded(OrderBy)
order by padded.OrderBy

按childid从tbl订单中选择*如果有7.11和1111.11,结果会是什么?列是nvarchar类型?应该是什么?根据我的评论,它将是111.1,然后是7.11。这不是你所期望的吗?@FelixPamittan不,我需要像7.11这样的订单,然后是111.1,我需要那个方式发布一个答案,但它只适用于2008年及以后。这可能值得一提——2005年只剩下大约6个月的延长支持期——它在2011年失去了主流支持。如果childid包含字母,会发生什么?它只会按字母数字顺序排列。但是如果。是否超过我们需要使用更多交叉申请??好的,我会检查,但很难手动提及交叉申请的数量。谢谢你和+1的建议。作者提到他有像1.23.22abc这样的字母数字值。我想它会在这里失败,strx.y.value'.'和'int',5@GiorgiNakeuri,找不到这样的提示?我认为这是字母数字排序的问题,但所有ID都是int。你可以看到它对这个问题的评论:@Damien_the_unsiver my db是2008,所以它在工作,问题是当chilid包含一些字符串或类似于1.23的内容时它失败了。22abc@GiorgiNakeuri,是的,这个重要信息来得很晚。。。谢谢你的提示!更改了处理填充字符串而不是填充int的方法。