Sql 对字母数字列进行排序

Sql 对字母数字列进行排序,sql,postgresql,alphanumeric,natural-sort,Sql,Postgresql,Alphanumeric,Natural Sort,我在数据库中有一列: Serial Number ------------- S1 S10 ... S2 S11 .. S13 我想对序列号进行排序并返回结果,如下所示这是一种简单的格式: order by length(Serial_Number), Serial_Number 这是因为前缀“S”在所有值上的长度都相同。以下是一种简单的格式: order by length(Serial_Number), Serial_Number 这是因为前缀“S”

我在数据库中有一列:

Serial Number
-------------
S1
S10
...
S2
S11
..
S13

我想对序列号进行排序并返回结果,如下所示这是一种简单的格式:

order by length(Serial_Number),
         Serial_Number

这是因为前缀“S”在所有值上的长度都相同。

以下是一种简单的格式:

order by length(Serial_Number),
         Serial_Number

这是因为前缀“S”在所有值上的长度相同。

对于Postgres,您可以使用如下内容:

select serial_number
from the_table
order by regexp_replace(serial_number, '[^0-9]', '', 'g')::integer;
regexp_replace将删除所有非数字字符,结果将被视为适合正确排序的数字

编辑1:

您可以使用新编号来限制查询结果:

select serial_number
from (
  select serial_number, 
         regexp_replace(serial_number, '[^0-9]', '', 'g')::integer as snum
  from the_table
) t 
where snum <= 10
order by snum;
在内部选择。或者,如果出于某种原因需要这些行,请在选择列表中处理这些行:

select serial_number
from (
  select serial_number, 
         case
            when length(regexp_replace(serial_number, '[^0-9]', '', 'g')) > 0 then regexp_replace(serial_number, '[^0-9]', '', 'g')::integer as snum
            else null -- or 0 whatever you need
         end as snum
  from the_table
) t 
where snum <= 10
order by snum;
这是一个很好的例子,说明了为什么不应该在一个列中混合两种不同的内容。如果所有序列号都有前缀S,则不应将其存储并将实数放入实整数或bigint列中


使用诸如NOT_SET之类的东西来指示缺少的值也是一个错误的选择。空值的发明正是出于这个原因:为了表示缺少数据。

对于Postgres,您可以使用如下内容:

select serial_number
from the_table
order by regexp_replace(serial_number, '[^0-9]', '', 'g')::integer;
regexp_replace将删除所有非数字字符,结果将被视为适合正确排序的数字

编辑1:

您可以使用新编号来限制查询结果:

select serial_number
from (
  select serial_number, 
         regexp_replace(serial_number, '[^0-9]', '', 'g')::integer as snum
  from the_table
) t 
where snum <= 10
order by snum;
在内部选择。或者,如果出于某种原因需要这些行,请在选择列表中处理这些行:

select serial_number
from (
  select serial_number, 
         case
            when length(regexp_replace(serial_number, '[^0-9]', '', 'g')) > 0 then regexp_replace(serial_number, '[^0-9]', '', 'g')::integer as snum
            else null -- or 0 whatever you need
         end as snum
  from the_table
) t 
where snum <= 10
order by snum;
这是一个很好的例子,说明了为什么不应该在一个列中混合两种不同的内容。如果所有序列号都有前缀S,则不应将其存储并将实数放入实整数或bigint列中


使用诸如NOT_SET之类的东西来指示缺少的值也是一个错误的选择。空值的发明正是出于这个原因:表示缺少数据。

因为只有第一个字符会破坏您的数字乐趣,只需使用数字值对其进行修剪和排序:

SELECT *
FROM   tbl
WHERE  right(serial_number, -1)::int < 11
ORDER  BY right(serial_number, -1)::int;

要求博士后9.1或更高版本。在旧版本中,使用子字符串x替换为10000。

因为只有第一个字符会破坏您的数字乐趣,只需使用以下数字值对其进行修剪和排序:

SELECT *
FROM   tbl
WHERE  right(serial_number, -1)::int < 11
ORDER  BY right(serial_number, -1)::int;

要求博士后9.1或更高版本。在旧版本中,使用子字符串x替换为10000。

谢谢。我没有意识到它对相同的前缀也适用。但是有没有办法把它限制到某个值呢?说到S5还是S10?@iDev。我真的不明白你的意思。limit接受多行,而不是一个值。谢谢。我不知道它对相同的前缀有效。但是有没有办法把它限制到某个值呢?说到S5还是S10?@iDev。我真的不明白你的意思。limit接受许多行,而不是一个值。为什么我们需要标志“g”?此外,是否有可能将结果集限制在S5或S10?@iDev:只是为了确定。如果开头后面还有其他非数字字符,则用g参数替换regexp_不会替换它们。它使replace成为全局的,而不仅仅是firs occurrencethanks@a_horse_和_no_name,但我不确定结果怎么可能只有到S10为止?错误:integer的输入语法无效:@iDev:这意味着其中的行不包含任何数字,例如,为什么我们需要标记“g”?此外,是否有可能将结果集限制在S5或S10?@iDev:只是为了确定。如果开头后面还有其他非数字字符,则用g参数替换regexp_不会替换它们。它使replace成为全局的,而不仅仅是第一个出现的带有\u no \u名称的@a_horse\u,但我不确定结果怎么可能只有到S10为止?错误:integer的输入语法无效:@iDev:这意味着其中有不包含任何数字的行,例如,对于此问题的一般解决方案,请参阅。如果您的值更简单、更一致,则可能会变得不必要的复杂。有关此问题的一般解决方案,请参阅。如果你的价值观更简单、更一致,那么它可能会变得不必要的复杂。