当列不属于同一类型时如何按列排序?



我在列中的字段如下所示:

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

编辑

既然你已经给出了具体的例子,我看到是108B把事情搞砸了。 试试这个:

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,因此这些值将首先排序。

最新更新