sql - 在 SQL 中对分层文本进行排序

标签 sql sql-server tsql hierarchy

我有一个带有 varchar 字段的表。该字段存储我想要排序的层次编号。

这是我的数据示例:

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);

关于sql - 在 SQL 中对分层文本进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29693687/

相关文章:

php - 我的 php/sql 脚本中出现错误?

sql - 在 SQL WHERE 子句中转义问号 (?)

sql - 使用 between operator 的 Hive 不等式连接

sql-server - 如何解析sql server中的xml以处理DateTime DataType中的NULL值

MySql/MSSQL - 检查处理记录 - 缩放?

mysql - 需要帮助解决此 SQL 查询

sql-server - 更新年份?

sql - 如何从包含自引用外键的表中删除所有数据

sql - 获取 2 个不同字符串之间的字符串的一部分

sql - 将记录从一列插入到同一范围或语句中的另一列