如何使用 SQL 表示多级订单的此 varchar 字段正确排序?

How can I correctly order by this varchar field representing a multiple level order using SQL?

我不是很喜欢数据库,我发现以下问题正在对旧遗留应用程序的 SQL 服务器数据库 进行查询。我声明很遗憾我无法更改数据库 structure\fields 类型(非常难看)

我有以下情况:

SELECT [Sottocategoria]
    ,[IdSottocategoria]
    ,[IdCategoria]
    ,[Note]
FROM [dbo].[PROT_TITOLARIO]
where IdCategoria = '5'
order by IdSottocategoria

我得到了这样的东西:

我已经突出显示了我的输出错误。如您所见,我正在尝试按 IdSottocategoria 字段(定义为 varchar)进行排序。

以这种方式排序是使用字母顺序排序(而不是我需要的将其视为数字)。

实际上我需要这个 IdSottocategoria 字段的递增顺序,如下所示:

5.0 --> 5.1 --> 5.2 --> 5.3 --> ............... --> 5.10 --> 5.11 --> ...........

请注意,此 IdSottocategoria 字段还可以包含以下值:5.0.05.0.1 或更多 "level" 作为 5.0.1.3.4

我如何尝试处理这种情况并实现这种行为?

编辑 1: 我正在添加数据:

USE [MY_DB]
GO
/****** Object:  Table [dbo].[PROT_TITOLARIO]    Script Date: 8/7/2019 11:38:11 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[PROT_TITOLARIO](
    [IdSottocategoria] [varchar](50) NOT NULL,
    [Sottocategoria] [varchar](500) NOT NULL,
    [IdCategoria] [varchar](50) NOT NULL,
    [Note] [varchar](max) NULL,
 CONSTRAINT [PK_PROT_TITOLARIO_NEW] PRIMARY KEY CLUSTERED 
(
    [IdSottocategoria] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO
SET ANSI_PADDING OFF
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'0', N'HR', N'IWG', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'0.0', N'CV', N'0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'0.1', N'test', N'0', NULL)
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'0.1.0', N'ghjghjg', N'0.1', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'0.1.0.0', N'ghghg', N'0.1.0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'0.1.0.0.0', N'sdf', N'0.1.0.0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'0.1.0.0.0.0', N'fsdfsdfsd', N'0.1.0.0.0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'0.1.0.0.0.0.0', N'dgdgdfg', N'0.1.0.0.0.0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'0.1.0.0.0.0.1', N'uiouoi', N'0.1.0.0.0.0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'0.1.0.0.0.0.2', N'yrtyrtyrtyrt', N'0.1.0.0.0.0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'0.1.0.0.1', N'HR - fghfhfghf', N'0.1.0.0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'0.2', N'bla', N'0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'0.3', N'AAA', N'0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'0.4', N'dasdas', N'0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'0.5', N'fghfghfgh', N'0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'0.6', N'HR - TEST PRIMO LIVELLO', N'0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'0.6.0', N'HR - TEST SECONDO LIVELLO', N'0.6', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'0.6.0.0', N'HR - TEST TERZO LIVELLO', N'0.6.0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'1', N'Commerciale', N'IWG', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'1.1', N'XXX', N'1', NULL)
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'1.1.0', N'Commerciale - bla', N'1.1', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'1.2', N'YYY', N'1', NULL)
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'1.3', N'ZZZ', N'1', NULL)
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'1.4', N'Commerciale - dsasdasd', N'1', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'2', N'Titolario - TEST LIVELLO 0', N'IWG', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'2.0', N'bhjbhjbhbjb', N'2', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'2.0.0', N'pippo', N'2.0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'2.0.1', N'Titolario - TEST LIVELLO 0 - dfgdfgdfg', N'2.0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'3', N'Titolario - TEST 2 LIVELLO 0', N'IWG', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'4', N'TEST 3 LIVELLO 0', N'IWG', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'4.0', N'TEST 3 LIVELLO 0 - LIVELLO 1', N'4', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'4.0.0', N'TEST 3 LIVELLO 0 - LIVELLO 2', N'4.0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'4.0.0.0', N'TEST 3 LIVELLO 0 - LIVELLO 3', N'4.0.0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'4.0.1', N'TEST 3 LIVELLO 0 - DASDASDAS', N'4.0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'5', N'ORDINAMENTO', N'IWG', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'5.0', N'ORDINAMENTO - ORD 0', N'5', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'5.0.0', N'ORDINAMENTO - test', N'5.0', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'5.1', N'ORDINAMENTO - ORD 1', N'5', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'5.10', N'ORDINAMENTO - ORD 10', N'5', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'5.11', N'ORDINAMENTO - ORD 11', N'5', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'5.12', N'ORDINAMENTO - ORD 12', N'5', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'5.2', N'ORDINAMENTO - ORD 2', N'5', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'5.3', N'ORDINAMENTO - ORD 3', N'5', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'5.4', N'ORDINAMENTO - ORD 4', N'5', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'5.5', N'ORDINAMENTO - ORD 5', N'5', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'5.6', N'ORDINAMENTO - ORD 6', N'5', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'5.7', N'ORDINAMENTO - ORD 7', N'5', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'5.8', N'ORDINAMENTO - ORD 8', N'5', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'5.9', N'ORDINAMENTO - ORD 9', N'5', N'')
GO
INSERT [dbo].[PROT_TITOLARIO] ([IdSottocategoria], [Sottocategoria], [IdCategoria], [Note]) VALUES (N'IWG', N'Titolario', N'-', N'Categoria')
GO

*

你可以简单地试试这个。

 SELECT [Sottocategoria]
,[IdSottocategoria]
,[IdCategoria]
,[Note]
 FROM [dbo].[PROT_TITOLARIO]
 where IdCategoria = '5'
 order by cast((SUBSTRING(IdSottocategoria,CharIndex('.',IdSottocategoria)+1, len(IdSottocategoria))) as int)

似乎这样就可以了:

SELECT *
FROM [dbo].[PROT_TITOLARIO]
ORDER BY TRY_CONVERT(hierarchyid,'/'+REPLACE(IdSottocategoria,'.','/')+'/');

请注意,这会将 "ID" 'IWG' 置于顶部,因为它无法转换为 hierarchyid。如果你想要 'IWG' 在底部,你可以这样做:

SELECT *
FROM [dbo].[PROT_TITOLARIO] PT
     CROSS APPLY (VALUES(TRY_CONVERT(hierarchyid,'/'+REPLACE(PT.IdSottocategoria,'.','/')+'/')))V(Hid)
ORDER BY CASE WHEN V.Hid IS NULL THEN 1 ELSE 0 END,
         V.Hid,
         PT.IdSottocategoria;

DB<>Fiddle

SELECT [Sottocategoria],
       [IdSottocategoria],
       [IdCategoria],
       [Note]
FROM [dbo].[PROT_TITOLARIO]
ORDER BY CAST('/'+REPLACE([IdSottocategoria], '.', '/')+'/' AS HIERARCHYID);