按以数字和字符串开头的列对SQL server表进行数字排序
我将按包含以下数据的列对SQL server表进行排序:按以数字和字符串开头的列对SQL server表进行数字排序,sql,sql-server,tsql,sql-order-by,Sql,Sql Server,Tsql,Sql Order By,我将按包含以下数据的列对SQL server表进行排序: 2.5.1 Sonstiges 1.1.1 Pflegstandards 5.1.7 Arbeitsgemeinschaften 1.2.1 Anforderungen 2.4.5 Betriebsarzt B Kernprozesse 1.1.1.4 Umgang mit 2.3.3 Kardiologie ...... 正如您所看到的,大多数记录都以数字开头,但也有一些记录以字符串开头。我使用以下查询来涵盖这两种情况: SELECT
2.5.1 Sonstiges
1.1.1 Pflegstandards
5.1.7 Arbeitsgemeinschaften
1.2.1 Anforderungen
2.4.5 Betriebsarzt
B Kernprozesse
1.1.1.4 Umgang mit
2.3.3 Kardiologie
......
正如您所看到的,大多数记录都以数字开头,但也有一些记录以字符串开头。我使用以下查询来涵盖这两种情况:
SELECT * from DocumentCategories
order by
case IsNumeric(replace( LEFT(name, CHARINDEX(' ', name)),'.',''))
when 0 then name
when 1 then cast(replace( LEFT(name, CHARINDEX(' ', name)),'.','') as int)
end
name
=====================
B Kernprozesse
1.1.1 Pflegstandards
1.2.1 Anforderungen
2.3.3 Kardiologie
2.4.5 Betriebsarzt
2.5.1 Sonstiges
5.1.7 Arbeitsgemeinschaften
1.1.1.4 Umgang mit
但是我得到一个关于varchar到int转换的错误(因为记录包含“B Kernprozesse”)。那么case/when在这里扮演什么角色?我错过什么了吗
我希望输出如下所示:
B Kernprozesse
1.1.1 Pflegstandards
1.2.1 Anforderungen
2.3.3 Kardiologie
2.4.5 Betriebsarzt
2.5.1 Sonstiges
5.1.7 Arbeitsgemeinschaften
1.1.1.4 Umgang mit
……你只是在找我吗
SELECT *
FROM (
VALUES
('2.5.1 Sonstiges'),
('1.1.1 Pflegstandards'),
('5.1.7 Arbeitsgemeinschaften'),
('1.2.1 Anforderungen'),
('2.4.5 Betriebsarzt'),
('B Kernprozesse'),
('1.1.1.4 Umgang mit'),
('2.3.3 Kardiologie')
) T(Str)
ORDER BY
CASE WHEN TRY_CAST(LEFT(Str, 1) AS INT) IS NOT NULL
THEN 0
ELSE 1
END
WITH A AS
(
SELECT *, ((LEN(Str) - LEN(REPLACE(Str, '.', ''))) * 2) + 1 N
FROM (
VALUES
('2.5.1 Sonstiges'),
('1.1.1 Pflegstandards'),
('5.1.7 Arbeitsgemeinschaften'),
('1.2.1 Anforderungen'),
('2.4.5 Betriebsarzt'),
('B Kernprozesse'),
('1.1.1.4 Umgang mit'),
('2.3.3 Kardiologie')
) T(Str)
)
SELECT *
FROM A
ORDER BY CASE WHEN TRY_CAST(REPLACE(LEFT(Str, N), '.', '') AS INT) IS NULL
THEN 0
ELSE CAST(REPLACE(LEFT(Str, N), '.', '') AS INT)
END
哪个会回来
+-----------------------------+
| Str |
+-----------------------------+
| 1.1.1 Pflegstandards |
| 5.1.7 Arbeitsgemeinschaften |
| 1.2.1 Anforderungen |
| 2.4.5 Betriebsarzt |
| 2.3.3 Kardiologie |
| 1.1.1.4 Umgang mit |
| 2.5.1 Sonstiges |
| B Kernprozesse |
+-----------------------------+
更新: 根据你问题的最新更新,你正在寻找
SELECT *
FROM (
VALUES
('2.5.1 Sonstiges'),
('1.1.1 Pflegstandards'),
('5.1.7 Arbeitsgemeinschaften'),
('1.2.1 Anforderungen'),
('2.4.5 Betriebsarzt'),
('B Kernprozesse'),
('1.1.1.4 Umgang mit'),
('2.3.3 Kardiologie')
) T(Str)
ORDER BY
CASE WHEN TRY_CAST(LEFT(Str, 1) AS INT) IS NOT NULL
THEN 0
ELSE 1
END
WITH A AS
(
SELECT *, ((LEN(Str) - LEN(REPLACE(Str, '.', ''))) * 2) + 1 N
FROM (
VALUES
('2.5.1 Sonstiges'),
('1.1.1 Pflegstandards'),
('5.1.7 Arbeitsgemeinschaften'),
('1.2.1 Anforderungen'),
('2.4.5 Betriebsarzt'),
('B Kernprozesse'),
('1.1.1.4 Umgang mit'),
('2.3.3 Kardiologie')
) T(Str)
)
SELECT *
FROM A
ORDER BY CASE WHEN TRY_CAST(REPLACE(LEFT(Str, N), '.', '') AS INT) IS NULL
THEN 0
ELSE CAST(REPLACE(LEFT(Str, N), '.', '') AS INT)
END
返回:
+-----------------------------+---+
| Str | N |
+-----------------------------+---+
| B Kernprozesse | 1 |
| 1.1.1 Pflegstandards | 5 |
| 1.2.1 Anforderungen | 5 |
| 2.3.3 Kardiologie | 5 |
| 2.4.5 Betriebsarzt | 5 |
| 2.5.1 Sonstiges | 5 |
| 5.1.7 Arbeitsgemeinschaften | 5 |
| 1.1.1.4 Umgang mit | 7 |
+-----------------------------+---+
如评论中所述,您可以像这样使用
TRY\u CAST
:
SELECT * FROM @DocumentCategories
ORDER BY
CASE WHEN TRY_CAST(replace( LEFT(name, CHARINDEX(' ', name)),'.','') AS INT) IS NULL
THEN 0
ELSE cast(replace( LEFT(name, CHARINDEX(' ', name)),'.','') as int)
END
如果您在2012版之前的SQL_SERVER环境中,则可以使用ISNUMERIC
并获得相同的结果:
SELECT * FROM @DocumentCategories
ORDER BY
CASE WHEN ISNUMERIC(replace( LEFT(name, CHARINDEX(' ', name)),'.','')) = 0
THEN 0
ELSE cast(replace( LEFT(name, CHARINDEX(' ', name)),'.','') as int)
END
以下是两种情况下的结果:
SELECT * from DocumentCategories
order by
case IsNumeric(replace( LEFT(name, CHARINDEX(' ', name)),'.',''))
when 0 then name
when 1 then cast(replace( LEFT(name, CHARINDEX(' ', name)),'.','') as int)
end
name
=====================
B Kernprozesse
1.1.1 Pflegstandards
1.2.1 Anforderungen
2.3.3 Kardiologie
2.4.5 Betriebsarzt
2.5.1 Sonstiges
5.1.7 Arbeitsgemeinschaften
1.1.1.4 Umgang mit
不要使用
ISNUMERIC()
它有一些问题。B Kernprozesse
是否可以像B Kernprozesse1.2.3
?ISNUMERIC
是一个糟糕的函数,如果我诚实的话。如果确实要测试字符串是否为数值,请使用TRY\u CONVERT
或TRY\u CAST
。此外,这里的问题是,您从大小写表达式返回了两种不同的数据类型[name]
显然是一个varchar
,但您的另一个表达式正在转换为int
。因此,[name]
也被强制转换为int
,这是由于数据类型前置,因此转换失败。您预期的输出是什么?请添加示例输出数据。1.1.1.4
与1.1.2
相比如何?现在,您的替换将这变成1114 vs 112
。预期输出会有帮助。如更新问题中所述,1.1.1.4应该是最后一个,1.2.1应该紧跟在1.1之后。1@Ali_dotNet您如何确定是否有3个努伯?5.4.或者它是静态的?正如你在我的查询中看到的,我使用replace来删除“.”,事实上数字的格式可能是1、1.1、1.1.1或1.1.1。我认为这个查询删除了前导数字(如果存在的话),然后按结果名称排序,我希望它按数字排序(当然是在删除“.”之后)@Ali_dotNet Yup,我知道你想做什么,并相应地更新答案。谢谢,但如果我还有一些以字符串开头的记录呢?我怎样才能把它们也分类呢?这个0在这里意味着什么?@Ali_dotNet你不能轻易地将数字和字母排序在一起。0表示如果案例
为真,则使用提供的值(本例中为0)。使用0是因为它比其他可能的整数低-如果大小写
为true(名称不是数字/无法转换),则将其置于列表顶部。它的作用是将所有非数值赋值为0,然后,orderby
比较0和0
,并声明一个平局。希望这是有意义的。这几乎就是我想要的,谢谢你的描述性评论:)@Ali_dotNet我建议在评论中为你的问题打开一个新的问题。我不知道这是否可能/如何可能,但我相信还有其他想法,你可以如何实现这一点。如果值不是数字,则尝试按字母排序,如果值是数字,则尝试按数字排序。祝你好运。像'1.12.123 Eins'
和'11.21.22 Zwei'
这样的值是如何排序的?