对 SQL 中的分层文本进行排序
Sorting hierarchical text in SQL
我有一个带有 varchar
字段的 table。此字段存储我要排序的层级编号。
这是我的数据示例:
1
1.1
1.1.1
1.1.2
1.1.3.
1.1.4
1.1.5
1.1.6.
1.1.7
10.
10.1
10.2
10.3
11.
11.1
11.2
2.
2.1
1.2.2
1.2.2.1
1.2.2.2
如何使用 T-SQL
实现以下结果:
1
1.1
1.1.1
1.1.2
1.1.3
1.1.4
1.1.5
1.1.6
1.1.7
1.2.2
1.2.2.1
1.2.2.2
2.
2.1
10.
10.1
10.2
10.3
11.
11.1
11.2
我试图用以下 SQL 拆分这些部分,但这并不优雅。
SELECT CASE WHEN CHARINDEX('.',SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.','')) = 0
THEN SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.','')
ELSE REPLACE(SUBSTRING(SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.',''),1, CHARINDEX('.',SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.',''))),'.','')
END AS FIRST_PART
,CASE WHEN CHARINDEX('.',SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.','')) > 0
THEN SUBSTRING(
SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.','')
,CHARINDEX('.',SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.','')) +1
,LEN( SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.','') )
)
ELSE '0'
END AS SECOND_PART
FROM TEST_TABLE
有更好的方法吗?
试试这个:
DECLARE @DataSource TABLE
(
[Value] VARCHAR(12)
);
INSERT INTO @DataSource ([Value])
VALUES ('1')
,('1.1')
,('1.1.1')
,('1.1.2')
,('1.1.3.')
,('1.1.4')
,('1.1.5')
,('1.1.6.')
,('1.1.7')
,('10.')
,('10.1')
,('10.2')
,('10.3')
,('11.')
,('11.1')
,('11.2')
,('2.')
,('2.1')
,('1.2.2')
,('1.2.2.1')
,('1.2.2.2');
SELECT *
FROM @DataSource
ORDER BY CAST('/' + IIF(RIGHT([Value],1) = '.', LEFT([Value], LEN([Value]) - 1), [Value]) + '/' AS HIERARCHYID);
您可以查看hierarchyid了解更多详情。 ORDER BY
子句中的检查只是删除值末尾的 .
(如果存在)。
您可以像这样使用简单的 CASE WHEN
更改 IIF
函数:
SELECT *
FROM @DataSource
ORDER BY CAST('/' + CASE WHEN RIGHT([Value],1) = '.' THEN LEFT([Value], LEN([Value]) - 1) ELSE [Value] END + '/' AS HIERARCHYID);
删除点并排序:
select column from table order by replace(column,'.','')
如果您希望 10 在 2 之前出现,则无需将 varchar 转换为数字。
我有一个带有 varchar
字段的 table。此字段存储我要排序的层级编号。
这是我的数据示例:
1
1.1
1.1.1
1.1.2
1.1.3.
1.1.4
1.1.5
1.1.6.
1.1.7
10.
10.1
10.2
10.3
11.
11.1
11.2
2.
2.1
1.2.2
1.2.2.1
1.2.2.2
如何使用 T-SQL
实现以下结果:
1
1.1
1.1.1
1.1.2
1.1.3
1.1.4
1.1.5
1.1.6
1.1.7
1.2.2
1.2.2.1
1.2.2.2
2.
2.1
10.
10.1
10.2
10.3
11.
11.1
11.2
我试图用以下 SQL 拆分这些部分,但这并不优雅。
SELECT CASE WHEN CHARINDEX('.',SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.','')) = 0
THEN SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.','')
ELSE REPLACE(SUBSTRING(SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.',''),1, CHARINDEX('.',SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.',''))),'.','')
END AS FIRST_PART
,CASE WHEN CHARINDEX('.',SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.','')) > 0
THEN SUBSTRING(
SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.','')
,CHARINDEX('.',SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.','')) +1
,LEN( SUBSTRING(LTRIM(RTRIM(NR)),1,LEN(NR)-1)+REPLACE(SUBSTRING(LTRIM(RTRIM(NR)),LEN(NR),1),'.','') )
)
ELSE '0'
END AS SECOND_PART
FROM TEST_TABLE
有更好的方法吗?
试试这个:
DECLARE @DataSource TABLE
(
[Value] VARCHAR(12)
);
INSERT INTO @DataSource ([Value])
VALUES ('1')
,('1.1')
,('1.1.1')
,('1.1.2')
,('1.1.3.')
,('1.1.4')
,('1.1.5')
,('1.1.6.')
,('1.1.7')
,('10.')
,('10.1')
,('10.2')
,('10.3')
,('11.')
,('11.1')
,('11.2')
,('2.')
,('2.1')
,('1.2.2')
,('1.2.2.1')
,('1.2.2.2');
SELECT *
FROM @DataSource
ORDER BY CAST('/' + IIF(RIGHT([Value],1) = '.', LEFT([Value], LEN([Value]) - 1), [Value]) + '/' AS HIERARCHYID);
您可以查看hierarchyid了解更多详情。 ORDER BY
子句中的检查只是删除值末尾的 .
(如果存在)。
您可以像这样使用简单的 CASE WHEN
更改 IIF
函数:
SELECT *
FROM @DataSource
ORDER BY CAST('/' + CASE WHEN RIGHT([Value],1) = '.' THEN LEFT([Value], LEN([Value]) - 1) ELSE [Value] END + '/' AS HIERARCHYID);
删除点并排序:
select column from table order by replace(column,'.','')
如果您希望 10 在 2 之前出现,则无需将 varchar 转换为数字。