我在数据库中有一个列:
Serial Number
-------------
S1
S10
...
S2
S11
..
S13
我想对序列号< = 10:
进行排序并返回如下结果S1
S2
S10
我试过的一种方法是:
select Serial_number form table where Serial_Number IN ('S1', 'S2',... 'S10');
这解决了目的,但寻找更好的方法
答案 0 :(得分:3)
以下是此格式的简便方法:
order by length(Serial_Number),
Serial_Number
这是有效的,因为前缀('S'
)在所有值上的长度相同。
答案 1 :(得分:2)
对于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;
修改2
如果您收到错误ERROR: invalid input syntax for integer: ""
,那么显然您在serial_number列中的值不会遵循您在问题中发布的格式。这意味着regexp_replace()从字符串中删除所有字符,因此像S
这样的字符串会导致这种情况。
为了防止这种情况,您需要使用以下方法从结果中排除这些行:
where length(regexp_replace(serial_number, '[^0-9]', '', 'g')) > 0
在内部选择中。或者,如果由于某种原因需要这些行,请在选择列表中处理:
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
,则不应将其存储并将实数放在真实的integer
(或bigint
)列中。
使用NOT_SET
之类的东西来表示缺失值也是一个糟糕的选择。由于这个原因,精确地发明了NULL
值:表明没有数据。
答案 2 :(得分:1)
由于只有第一个角色会破坏你的数字乐趣,只需用right()
修剪它并按数值排序:
SELECT *
FROM tbl
WHERE right(serial_number, -1)::int < 11
ORDER BY right(serial_number, -1)::int;
需要Postgres 9.1或更高版本。在旧版本中,使用substring (x, 10000)
替代。