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:这意味着其中有不包含任何数字的行,例如,对于此问题的一般解决方案,请参阅。如果您的值更简单、更一致,则可能会变得不必要的复杂。有关此问题的一般解决方案,请参阅。如果你的价值观更简单、更一致,那么它可能会变得不必要的复杂。