【问题标题】:How to sort alphanumeric string in SQL Server如何在 SQL Server 中对字母数字字符串进行排序
【发布时间】:2011-08-04 16:29:26
【问题描述】:

我想对一个字母数字字符串进行排序...

示例字符串:

D12,D13
F19,F20
A12,A13
F10,F11
D14
A1,A2
A5,A6
D4,D5
F5,F6,F7

期望的输出:

A1,A2
A5,A6
A12,A13
D4,D5
D12,D13
D14
F5,F6,F7
F10,F11
F19,F20

帮帮我!!!!

【问题讨论】:

  • 这不是一个尝试在 SQL 中执行的好过程。您可以在调用应用程序中执行此操作吗?
  • 总是以单个字母开头吗?
  • 喂。这种双重解析不仅是因为您有几组要一起排序的字符串,而且组中的字符串数量甚至不一致(最后一组有 3 个元素,而不是 2 个)。我建议 CLR 或您的应用程序代码对这些字符串的排序进行了比 T-SQL 更好的优化。
  • 您能否指定您使用的 SQL Server 版本?我还冒昧地编辑了标题(无需大喊大叫)。
  • 当像排序这样简单的事情变得困难时,您可以确定是糟糕的设计导致了它。通过更改表格来纠正问题。永远不要每列存储一个以上的值。在这里,我看到了一个以逗号分隔的复合值列表。将复合值(字母数字)拆分为两列(一列用于字母部分,另一列用于数字)。此外,将逗号分隔的列表拆分为额外的行,然后ORDER BY 将很简单。

标签: sql-server sql-server-2008 sql-server-2008-r2


【解决方案1】:

基于新的要求和@kuru kuru 的回答,我希望这个 order by 条款能说明为什么规范化是一件好事。仅仅因为它对 JSON 和 Ajax 有好处并不意味着您应该这样对待您的数据库:

DECLARE @t TABLE (x VARCHAR(32));

INSERT @t VALUES
  ('D12,D13'),
  ('F19,F20'),
  ('A12,A13'),
  ('F10,F11'),
  ('D14'),
  ('A1,A2'),
  ('A5,A6'),
  ('D4,D5'),
  ('F5,F6,F7'),
  ('AA1,AA2'),
  ('Z98,Z99');

SELECT x FROM @t
ORDER BY CASE 
    WHEN UPPER(x) LIKE '[A-Z][A-Z]%'
    THEN 'Z' + LEFT(x,2) ELSE LEFT(x,1) END,
    CONVERT(INT, 
      CASE WHEN x LIKE '%,%' THEN 
        SUBSTRING(x, PATINDEX('%[0-9]%', x), 
        CHARINDEX(',', x)-PATINDEX('%[0-9]%', x))
      ELSE 
        SUBSTRING(x, PATINDEX('%[0-9]%', x), 32)
      END
    );

【讨论】:

  • A12,A13A1,A2 之前排序
  • 在这种情况下,F5、F6、F7 出现在 F19、F20 和 F10、F11 之后
  • 我认为这不是一件好事。这是一个丑陋的黑客,几乎没有隐藏一个可怕的底层设计。但是,很高兴能提供帮助。 :-)
  • 是的,我知道,但是在具有大结构和大小的实时数据库中进行更改是不可能的.....无论如何再次感谢。
  • 好吧,如果您尝试针对“大型结构和大小”执行这种排序,我很想知道它的运行情况有多糟糕......希望您撤回一小部分行并且只应用排序作为第二步。
【解决方案2】:

正如@JNK 和@Aaron Bertrand 所提到的,T-SQL 并不是这项任务的最佳选择。

话虽如此,有几个问题需要解决。

  1. 您必须将每个项目分成两个部分,即字母部分和数字部分,否则“A5,...”将无法排在“A12,”之前。 ..”,因为在比较字符串值时,“A5”在“A1”之后。您必须解析这些值并将“A5”转换为“A05”(或者您需要的许多有效数字)才能获得正确的排序顺序。

  2. 您是否忽略了每个字符串中逗号后的附加项目?如果答案是否定的,那么您必须对字符串中的每个值执行 #1 中描述的处理。例如,是否可以有“A5,A6”并且您希望该值排在“A5,A12”之前?

将字符串中的值标准化后,就可以进行比较和排序了。

【讨论】:

  • 感谢您的回答。我的答案是肯定的,我忽略了每个字符串中逗号后的附加项,因为它是逗号前第一个字母数字值的前一个值。一个是固定的。那么现在可以进行排序了吗?
  • 但就排序算法而言,它不是一个数值。它是一个字符串。所以比较将从第一个字符开始,在这种情况下都是'A'。然后是第二个字符,“A5”与“A1”。比较表明 A1 在 A5 之前,即使通过查看它,您也知道它实际上是 A5 与 A12。因此,您必须先规范化数字部分,然后才能进行真正的排序。 “A05”与“A12”。
  • 但在这种情况下我们不能分隔“12”吗?
【解决方案3】:

我不敢相信每个人都在说关于 TSQL 的所有这些卑鄙的事情。 :-)

您不必在对数据进行排序之前对其进行规范化。 (好吧,在任何情况下都没有明确说明——SQL 引擎在处理 ORDER BY 子句时可以戴上一些啤酒眼镜,它会正常工作)。

这是一个在 TSQL 中工作的示例...我知道它看起来像右侧没有理由正确排序,但它确实正确排序。

declare @table TABLE (item varchar(10))
insert into @table(item) values('FF5')
insert into @table(item) values('Z10')
insert into @table(item) values('F15')
insert into @table(item) values('F20')
insert into @table(item) values('A7')
insert into @table(item) values('A12')

SELECT
    item
FROM
    @table
ORDER BY
    CASE WHEN SUBSTRING(item,2,1) LIKE '[A-Z]' THEN LEFT(item,2) ELSE LEFT(item,1) END

【讨论】:

  • 你试过了吗,还是你只是这么说?我运行了它,它确实为我正确排序(SQL-Server 2005 和 2008)
  • 好的——现在他说左边可能有两个字母字符...返回查询窗口...
  • OK @Filip -- 现在它又可以工作了 -- 只需要更改顺序以考虑左侧的两个 alpha。
  • 它没有正确排序.. 有一个字符串有两个值,如 A11,A12,用逗号分隔......
  • 该死——在最新评论中再次更改了要求——回到绘图板。
猜你喜欢
  • 1970-01-01
  • 2021-09-19
  • 2019-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-05
相关资源
最近更新 更多