我在列中的字段如下所示:
2/8B, 3, 3/8B, 4/8B, 2, 6, 4/9, 9, 8/9, 8, 7, 1, 5/9, 10, 3/9, 2/9, 7/9, 6/8B, 6/9, 1/9, 5, 8B, 5/8B, 4
我需要按以下方式对此列表进行排序:
1, 1/9, 2, 2/8B, 2/9, 3, 3/8B, 3/9, 4, 4/8B, 4/9, 5, 5/8B, 5/9, 6, 6/8B, 6/9, 7, 7/9, 8, 8/9, 8B, 9, 10
如何按顺序创建此输出?
消除任何混淆(1/2)不是一小部分。 "/"只是一个分隔符。
这个问题充满了问题。 本质上,您正在尝试编写一个排序函数,该函数可以查看这些字符串并对其进行人工解释。 这意味着最终命名架构将以任何人都能理解的方式更改,但您的代码不会,然后您就会遇到错误。
我不知道你怎么不走这条路。 但要尽可能多地捍卫、警告和提升。
我不明白;使用您提供的字符确实按照您要求的顺序排序。 试一试:
SELECT Test
FROM (
SELECT '38a' AS Test
UNION
SELECT '1'
UNION
SELECT '1/2'
UNION
SELECT '12'
) MyData
ORDER BY Test ASC
编辑
既然你已经给出了具体的例子,我看到是10
和8B
把事情搞砸了。 试试这个:
SELECT YourCol
FROM YourTable
ORDER BY CAST(REPLACE(REPLACE(REPLACE(YourCol, 'B', '.99'), '/', '.'),
'.8.99', '.899') AS NUMERIC(18, 4))
这将按以下方式排序:
1, 1/9, 2, 2/8B, 2/9, 3, 3/8B, 3/9, 4, 4/8B, 4/9, 5, 5/8B, 5/9, 6, 6/8B, 6/9, 7, 7/9, 8,8/9, 8B, 9, 10
这很丑陋,但它有效。 如果除了 B 之外还有其他字母,则必须更改脚本来处理它。
我假设您排序的列是字符数据类型(因为某些值是非数字字符)——所以一个简单的 ORDER BY 将起作用
select '38a' as value
union
select '12'
union
select '1/2'
union
select '1'
order by value
这不会给你你想要
您可以使用的一个技巧是从字符串中提取前导整数,按整数值排序,然后按字符串排序。
我不知道在SQL Server中有任何"简单"的方法可以做到这一点(即不构建函数)。
使用本机内置 SQL Server 函数执行此操作的一种方法是使用 PATINDEX 函数搜索"数字"和"非数字"的起始位置,然后使用这些值来确定前导整数的长度。 使用 SUBSTRING 和 CONVERT 函数提取前导整数值。
它并不漂亮:
ORDER BY
CASE WHEN PATINDEX('[0-9]%', t.str ) = 1
THEN
CASE WHEN PATINDEX('%[^0-9]%', t.str ) > 0
THEN CONVERT(INTEGER,SUBSTRING( t.str ,1,PATINDEX('%[^0-9]%', t.str )-1))
ELSE CONVERT(INTEGER, t.str )
END
ELSE NULL
END
, t.str
笔记:
t.str
是返回字符串值的表达式的占位符。
对于测试用例中给出的所有值,这符合指定的要求。
此外,当遇到"意外"值(例如,空字符串 '' 或没有前导整数的字符串)时,这不会引发异常(即导致语句失败)。
这仅处理字符串的"前导整数"部分。之后的所有内容都作为字符串进行比较。(这意味着例如"6/10B"将在"1/8B"之前排序,因为"/1"<"/8"。
对于整数比较,将忽略前导整数值上的任何前导零,并在字符串比较中考虑。(这意味着例如"05/9"将在"5/8"之前排序,因为 5=5 但"0"<"5")
对于排序操作,将为任何没有前导数字的字符串值分配一个整数值 NULL,因此这些值将首先排序。