0

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

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)不是一个分数。“/”只是一个分隔符。

4

4 回答 4

1

这个问题充满了问题。本质上,您正在尝试编写一个排序函数,可以查看这些字符串并对它们进行人工解释。这意味着最终命名模式将以任何人都能理解的方式更改,但您的代码不会,然后您就会遇到错误。

我不知道你怎么不走这条路。但要尽可能地捍卫、警告和提升。

于 2012-06-30T15:39:19.137 回答
0

我不明白;使用您提供的字符确实按您要求的顺序排序。试一试:

SELECT Test
FROM (
    SELECT '38a' AS Test
    UNION
    SELECT '1'
    UNION 
    SELECT '1/2'
    UNION
    SELECT '12'
) MyData
ORDER BY Test ASC

编辑

既然你已经给出了具体的例子,我知道是10and8B把事情搞砸了。试试这个:

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 之外的其他字母,则必须更改脚本以处理它。

于 2012-06-29T17:04:08.717 回答
0

我假设您要排序的列是字符数据类型(因为有些值是非数字字符)——所以一个简单的 ORDER BY 就可以了

select '38a' as value
 union
select '12'
 union
select '1/2'
 union
select '1'
order by value

这不会给你你正在寻找的结果吗?

于 2012-06-29T17:10:38.360 回答
0

您可以使用的一种技巧是从字符串中提取前导整数,按整数值排序,然后按字符串排序。

我不知道在 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 用于排序操作,因此它们将首先排序。

于 2012-06-29T20:58:08.637 回答