SQL Order Chars数字 - 节点分组

时间:2013-07-25 06:24:59

标签: sql sql-server casting

我有一列数字存储为以句点分隔的字符 - 用作父子分组机制。由于varchar的性质和在11之前出现的问题而导致排序问题,如下面的粗体突出显示:

01
01.01
01.02
01.03
01年3月1日
01.03.02
...
10年3月1日
01.03.100
01.03.101
11年3月1日
01.03.12
...
01.04
01年4月1日
01.04.01.01
01.04.01.02
01.04.01.03
02年4月1日
03年4月1日
02
02.01

有关如何以数字方式订购这些字符的任何想法?可能存在无限的子节点,因此这不是不可能的:

nn.nn.nn.nn.nn.nn.nn.nn.nn.nn等

谢谢!

1 个答案:

答案 0 :(得分:3)

如果树的深度 1 有限制,那么你可以这样写:

declare @t table (OrdCol varchar(50) not null)
insert into @t (OrdCol) values
('01'),
('01.01'),
('01.02'),
('01.03'),
('01.03.01'),
('01.03.02'),
('01.03.10'),
('01.03.100'),
('01.03.101'),
('01.03.11'),
('01.03.12'),
('01.04'),
('01.04.01'),
('01.04.01.01'),
('01.04.01.02'),
('01.04.01.03'),
('01.04.02'),
('01.04.03'),
('02'),
('02.01')

select OrdCol from
(select OrdCol,CAST('<a><b>' + REPLACE(OrdCol,'.','</b><b>') + '</b></a>' as xml) as xOrd from @t
) t
order by
    xOrd.value('(a/b)[1]','int'),
    xOrd.value('(a/b)[2]','int'),
    xOrd.value('(a/b)[3]','int'),
    xOrd.value('(a/b)[4]','int'),
    xOrd.value('(a/b)[5]','int'),
    xOrd.value('(a/b)[6]','int'),
    xOrd.value('(a/b)[7]','int'),
    xOrd.value('(a/b)[8]','int'),
    xOrd.value('(a/b)[9]','int'),
    xOrd.value('(a/b)[10]','int')

1 为什么我要求澄清一个关于“无限”儿童被解释的方式的问题的评论。此查询处理每个级别的无限数量的子项,但只处理最多10个的深度。


无限深度版本,如果任何数字最多只有一个0,则可以使用

select OrdCol from
(select OrdCol,CAST(REPLACE(REPLACE('.' + OrdCol + '.','.0','.'),'.','/') as hierarchyid) as hOrd from @t
) t
order by
    hOrd

它只是对字符串进行管理,直到它符合可转换为hierarchyid的格式,该格式已经按照您预期的顺序执行排序。当然,如果这是有效的,您可以考虑更改列数据类型以使用此类型。